Commit 3b381525 authored by wind.wang's avatar wind.wang

init

parents
node_modules/
android/build
\ No newline at end of file
import { NativeModules } from 'react-native';
const { RNMonitor } = NativeModules;
export const REAL_TIME = RNMonitor.REAL_TIME; //实时上传(任何有网络的情况下)
export const REAL_TIME_WIFI = RNMonitor.REAL_TIME_WIFI; //实时WiFi上传(仅WiFi下实时上传)
// export const WIFI = RNMonitor.WIFI; //WiFi下上传(应用启动时 并且是WiFi环境下 才上传log)
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>react-native-monitor</name>
<comment>Project react-native-monitor created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>
connection.project.dir=../../../../android
eclipse.preferences.version=1
<?xml version="1.0" encoding="UTF-8"?>
<module external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
apply plugin: 'com.android.library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion "${rootProject.ext.buildToolsVersion}"
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
lintOptions {
warning 'InvalidPackage'
}
useLibrary 'org.apache.http.legacy'
}
dependencies {
implementation "com.facebook.react:react-native:+" // From node_modules
implementation group:'com.google.code.gson', name:'gson', version:'2.5'
implementation 'org.litepal.android:core:1.4.1'
implementation 'com.loopj.android:android-async-http:1.4.8'
}
\ No newline at end of file
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Thu Mar 02 12:49:02 CST 2017
sdk.dir=/Users/yhrun/workspace/Android/IDE/sdk
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":react-native-monitor" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../../../android" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":react-native-monitor" />
</configuration>
</facet>
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
<option name="RES_FOLDERS_RELATIVE_PATH" value="" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
<option name="PROJECT_TYPE" value="1" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7">
<output url="file://$MODULE_DIR$/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes" />
<output-test url="file://$MODULE_DIR$/build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debug/compileDebugAidl/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debug/compileDebugRenderscript/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/aidl_source_output_dir/debugAndroidTest/compileDebugAndroidTestAidl/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/renderscript_source_output_dir/debugAndroidTest/compileDebugAndroidTestRenderscript/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/test/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTestDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/aapt_friendly_merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotation_processor_list" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/check_manifest_result" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/compile_only_not_namespaced_r_class_jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/full_jar" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/intermediate-jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javac" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/library_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/library_manifest" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/merged_manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/packaged_res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/public_res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shader_assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.12.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:customview-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:fbcore-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:localbroadcastmanager-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:drawee-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:interpolator-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.12.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel-1.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.google.code.gson:gson:2.5@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:drawerlayout-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:collections:28.0.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:documentfile-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:cursoradapter-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-1.1.1" level="project" />
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:versionedparcelable-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader-0.6.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.core:runtime-1.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.infer.annotation:infer-annotation:0.11.2@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:print-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.react:react-native-0.59.1" level="project" />
<orderEntry type="library" name="Gradle: com.loopj.android:android-async-http:1.4.8@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:loader-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" />
<orderEntry type="library" name="Gradle: org.litepal.android:core-1.4.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:viewpager-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-fragment-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core-1.1.1" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:support-compat-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.15.0@jar" level="project" />
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7-28.0.0" level="project" />
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base-1.10.0" level="project" />
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime-1.1.1" level="project" />
<orderEntry type="library" name="Gradle: org.apache.http.legacy-android-28" level="project" />
</component>
</module>
\ No newline at end of file
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.terminus.monitor">
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="TerminusMonitor" />
<version value="10" />
<list>
<mapping class="io.terminus.monitor.model.DeviceInfo" />
<mapping class="io.terminus.monitor.model.ErrorModel" />
<mapping class="io.terminus.monitor.model.EventModel"/>
<mapping class="io.terminus.monitor.model.PageModel"/>
<mapping class="io.terminus.monitor.model.PerformanceModel"/>
<mapping class="io.terminus.monitor.model.RequestModel"/>
</list>
</litepal>
\ No newline at end of file
package io.terminus.monitor;
import android.text.TextUtils;
import android.util.Log;
import io.terminus.monitor.model.Enum.UploadModel;
/**
* User : yh
* Date : 17/2/21
*/
public class AnalyticsConfig {
private static String appKey = "43ce6feebf3c459286e810600e2cb104";
private static String base_url = "https://analytics.terminus.io/collect";
private static UploadModel uploadModel = UploadModel.WIFI_LIMIT;
private static String DeviceId ; //设备id
private static String userId; //用户id
public static void setAppKey(String appKey){
AnalyticsConfig.appKey = appKey;
}
public static String getAppKey(){
if(TextUtils.isEmpty(appKey)){
Log.e("Config Error","appkey is empty,please check");
}
return appKey;
}
public static void setUploadModel(UploadModel model){
AnalyticsConfig.uploadModel = model;
}
public static UploadModel getUploadModel(){
return AnalyticsConfig.uploadModel;
}
public static void setDeviceId(String deviceId){
AnalyticsConfig.DeviceId = deviceId;
}
public static String getDeviceId(){
return AnalyticsConfig.DeviceId;
}
public static void setBase_url(String url){
AnalyticsConfig.base_url = url;
}
public static String getDomain(){
return AnalyticsConfig.base_url;
}
public static String getUserId(){
return AnalyticsConfig.userId;
}
public static void setUserId(String userId){
AnalyticsConfig.userId = userId;
}
}
package io.terminus.monitor;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import org.litepal.LitePal;
import java.util.HashMap;
import java.util.Map;
import io.terminus.monitor.model.BaseModel;
import io.terminus.monitor.model.DeviceInfo;
import io.terminus.monitor.model.Enum.UploadModel;
import io.terminus.monitor.model.ErrorModel;
import io.terminus.monitor.model.EventModel;
import io.terminus.monitor.model.PageModel;
import io.terminus.monitor.model.RequestModel;
import io.terminus.monitor.model.PerformanceModel;
import io.terminus.monitor.module.LitePalHelper;
import io.terminus.monitor.module.UploadManager;
import io.terminus.monitor.util.DeviceUtil;
import io.terminus.monitor.util.ToolUtil;
/**
* User : yh
* Date : 17/2/21
*/
public class RNMobClickAgent {
private static final String TAG = "TerminusMobClick";
private static RNMobClickAgent agent;
private Map<String,PageModel> pageInfo;
private RNMobClickAgent(){
pageInfo = new HashMap<>();
}
private static Context mContext;
public static RNMobClickAgent getInstance(){
if(agent == null){
agent = new RNMobClickAgent();
}
return agent;
}
public void init(Context mContext){
RNMobClickAgent.mContext = mContext;
LitePal.initialize(mContext);
LitePalHelper.getInstance().LogModelRegist(DeviceInfo.class);
LitePalHelper.getInstance().LogModelRegist(ErrorModel.class);
LitePalHelper.getInstance().LogModelRegist(EventModel.class);
LitePalHelper.getInstance().LogModelRegist(PageModel.class);
LitePalHelper.getInstance().LogModelRegist(PerformanceModel.class);
LitePalHelper.getInstance().LogModelRegist(RequestModel.class);
UploadManager.getInstance().init(mContext);
AnalyticsConfig.setDeviceId(DeviceUtil.getDeviceId(mContext));
}
public void setAppKey(String appkey){
//// TODO: 17/2/21
AnalyticsConfig.setAppKey(appkey);
UploadManager.getInstance().addDeviceTask(DeviceUtil.getDeviceInfo(RNMobClickAgent.mContext));
}
public void setChannel(String channel){
//// TODO: 17/2/21
}
public void onEvent(BaseModel event){
UploadManager.getInstance().addTask(modleAppendInfo(event));
}
public void setUploadModel(UploadModel model){
AnalyticsConfig.setUploadModel(model);
}
public void setSignin(String userId){
AnalyticsConfig.setUserId(userId);
}
private BaseModel modleAppendInfo(BaseModel model){
if(!TextUtils.isEmpty(AnalyticsConfig.getUserId())){
model.setUid(AnalyticsConfig.getUserId());
}
model.setDate(ToolUtil.getNowTime());
return model;
}
public void onPageStart(String pageName,String lastPage){
if(TextUtils.isEmpty(pageName)){
Log.e(TAG,"pageName is empty");
return;
}
PageModel model = new PageModel();
model.setDt(pageName);
model.setDr(lastPage);
model.setSt(ToolUtil.getNowTimeMillis());
pageInfo.put(pageName,model);
}
public void onPageEnd(String pageName){
if(!pageInfo.containsKey(pageName) ){
Log.e(TAG,pageName+" not exit");
return;
}
PageModel model = pageInfo.get(pageName);
model.setTp(String.valueOf((ToolUtil.getNowTimeMillis() - model.getSt())/1000));
onEvent(model);
pageInfo.remove(pageName);
}
public Context getContext(){
return mContext;
}
}
package io.terminus.monitor;
import android.support.annotation.UiThread;
import android.view.Choreographer;
import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.NativeModuleCallExceptionHandler;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableNativeMap;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.debug.FpsDebugFrameCallback;
import com.facebook.react.modules.core.ChoreographerCompat;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import io.terminus.monitor.model.Enum.UploadModel;
import io.terminus.monitor.model.ErrorModel;
import io.terminus.monitor.model.EventModel;
import io.terminus.monitor.model.PageModel;
import io.terminus.monitor.module.CrashHandler;
import io.terminus.monitor.module.PerFormanceTool;
import io.terminus.monitor.util.ToolUtil;
import io.terminus.monitor.model.RequestModel;
public class RNMonitorModule extends ReactContextBaseJavaModule implements LifecycleEventListener{
private final ReactApplicationContext reactContext;
private FpsDebugFrameCallback callback;
private Timer timer ;
private static final String WIFI_LIMIT = "WIFI_LIMIT";
private static final String REAL_TIME_WIFI = "REAL_TIME_WIFI";
private static final String REAL_TIME = "REAL_TIME";
public RNMonitorModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
RNMobClickAgent.getInstance().init(reactContext.getApplicationContext());
PerFormanceTool.getInstance().init(reactContext);
}
@ReactMethod
public void init(String appkey, int model) {
RNMobClickAgent.getInstance().setAppKey(appkey);
UploadModel uModel = UploadModel.getModel(model);
RNMobClickAgent.getInstance().setUploadModel(uModel);
UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
if (callback == null) {
callback = new FpsDebugFrameCallback(reactContext);
callback.start();
}
}
});
if(timer != null){
return;
}
// timer = new Timer();
// timer.schedule(new TimerTask() {
// @Override
// public void run() {
// UiThreadUtil.runOnUiThread(new Runnable() {
// @Override
// public void run() {
// if (callback != null) {
// PerFormanceTool.getInstance().setFPSsetFPS(callback.getFPS(), callback.getJSFPS());
// }
// }
// });
// }
// }, 3000, 3000);
reactContext.addLifecycleEventListener(this);
}
@ReactMethod
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put(REAL_TIME, UploadModel.REAL_TIME.model);
constants.put(WIFI_LIMIT, UploadModel.WIFI_LIMIT.model);
constants.put(REAL_TIME_WIFI,UploadModel.REAL_TIME_WIFI.model);
return constants;
}
@ReactMethod
public void onSignIn(String userId) {
RNMobClickAgent.getInstance().setSignin(userId);
}
@ReactMethod
public void onCusEvent(ReadableMap map) {
ReadableNativeMap nativeMap = (ReadableNativeMap) map;
String event_str = new Gson().toJson(nativeMap.toHashMap());
EventModel eventModel = new Gson().fromJson(event_str, EventModel.class);
RNMobClickAgent.getInstance().onEvent(eventModel);
}
@ReactMethod
public void sendRequest(ReadableMap map) {
ReadableNativeMap nativeMap = (ReadableNativeMap) map;
String event_str = new Gson().toJson(nativeMap.toHashMap());
RequestModel requestModel = new Gson().fromJson(event_str, RequestModel.class);
RNMobClickAgent.getInstance().onEvent(requestModel);
}
@ReactMethod
public void onError(ReadableMap map) {
ReadableNativeMap nativeMap = (ReadableNativeMap) map;
String event_str = new Gson().toJson(nativeMap.toHashMap());
ErrorModel errorModel = new Gson().fromJson(event_str, ErrorModel.class);
RNMobClickAgent.getInstance().onEvent(errorModel);
}
@ReactMethod
public void onPageStart(String pageName,String lastPage) {
RNMobClickAgent.getInstance().onPageStart(pageName,lastPage);
}
@ReactMethod
public void onPageEnd(String pageName) {
RNMobClickAgent.getInstance().onPageEnd(pageName);
}
@ReactMethod
public void pageLoadTime(String pageName,String pageTime) {
PerFormanceTool.getInstance().pageLoadTime(pageName,pageTime);
}
@Override
public String getName() {
return "RNMonitor";
}
@Override
public void onHostResume() {
}
@Override
public void onHostPause() {
}
@Override
public void onHostDestroy() {
if(timer != null ){
timer.cancel();
timer = null;
}
}
}
\ No newline at end of file
package io.terminus.monitor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
public class RNMonitorPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new RNMonitorModule(reactContext));
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
\ No newline at end of file
package io.terminus.monitor.model;
import com.google.gson.Gson;
import com.loopj.android.http.RequestParams;
import org.litepal.crud.DataSupport;
import java.lang.reflect.Method;
/**
* User : yh
* Date : 17/2/22
*/
public class BaseModel extends DataSupport{
public String toString(){
return new Gson().toJson(this);
}
public long getId(){
return getBaseObjId();
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getNs() { return ns; }
public void setNs(String ns) {
this.ns = ns;
}
public String getAv() { return av; }
public void setAv(String av) {
this.av = av;
}
public String getVid() { return vid; }
public void setVid(String vid) {
this.vid = vid;
}
public String getAk() { return ak; }
public void setAk(String ak) {
this.ak = ak;
}
public String getDp() { return dp; }
public void setDp(String dp) {
this.dp = dp;
}
public String getDh() { return dh; }
public void setDh(String dh) {
this.dh = dh;
}
public String getCid() { return cid; }
public void setCid(String cid) {
this.cid = cid;
}
public String getGps() { return gps; }
public void setGps(String gps) {
this.gps = gps;
}
public String getExtra() { return extra; }
public void setExtra(String extra) {
this.extra = extra;
}
public String getMd() {
return md;
}
public void setMd(String md) {
this.md = md;
}
public String getOsn() {
return osn;
}
public void setOsn(String osName) {
this.osn = osn;
}
public String getOsv() {
return osv;
}
public void setOsv(String osv) {
this.osv = osv;
}
public String getBr() {
return br;
}
public void setBr(String br) {
this.br = br;
}
public String getUa() {
return ua;
}
public void setUa(String ua) {
this.ua = ua;
}
private String uid; //登录用户id
private String date; //时间
private String ns; //网络状态
private String av; //应用版本
private String ak; //应用id
private String vid; //访问id
private String dp; //界面名称
private String dh; //应用名
private String cid; //客户端表示,uuid
private String gps; //定位信息
private String ua; //ua信息
private String extra; //扩展
//设备品牌
private String br;
//设备型号
private String md;
// 系统名称
private String osn;
//系统版本
private String osv;
}
package io.terminus.monitor.model;
import org.litepal.crud.DataSupport;
/**
* User : yh
* Date : 17/2/20
*/
public class DeviceInfo extends BaseModel{
public String getSr() {
return sr;
}
public void setSr(String sr) {
this.sr = sr;
}
public String getCh() {
return ch;
}
public void setCh(String ch) {
this.ch = ch;
}
public int getJb() {
return jb;
}
public void setJb(int jb) {
this.jb= jb;
}
public String getRom() {
return rom;
}
public void setRom(String rom) {
this.rom = rom;
}
public String getMem() { return mem; }
public void setMem(String mem) {
this.mem = mem;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getSdk() {
return sdk;
}
public void setSdk(String sdk) {
this.sdk = sdk;
}
public String getSd() {
return sd;
}
public void setSd(String sd) {
this.sd = sd;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
//分辨率
private String sr;
//渠道
private String ch;
// 是否越狱
private int jb;
//磁盘大小
private String rom;
//内存
private String mem;
//cpu
private String cpu;
//sd 卡
private String sd;
//sdk信息
private String sdk;
private String t = "device";
}
package io.terminus.monitor.model.Enum;
/**
* User : yh
* Date : 17/2/21
*/
public enum NetInfoEnum {
WIFI("Wifi"),UNKNOWN("unknown"),G3("3G"),G4("4G"),OFFLINE("offline"),G2("2G");
private String status;
NetInfoEnum(String status){
this.status = status;
}
public String getStatus(){
return status;
}
}
package io.terminus.monitor.model.Enum;
/**
* User : yh
* Date : 17/2/22
*/
public enum UploadModel {
WIFI_LIMIT(0),REAL_TIME(1),REAL_TIME_WIFI(2);;
public int model;
UploadModel(int model){
this.model = model;
}
public static UploadModel getModel(int value) {
for(UploadModel model : UploadModel.values()){
if(model.model == value){
return model;
}
}
return WIFI_LIMIT;
}
}
package io.terminus.monitor.model;
import org.litepal.crud.DataSupport;
/**
* User : yh
* Date : 17/2/21
*/
public class ErrorModel extends BaseModel{
public String getErm() {
return erm;
}
public void setErm(String erm) {
this.erm = erm;
}
public String getSta() {
return sta;
}
public void setSta(String sta) {
this.sta = sta;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
private String erm; // 错误信息
private String sta; // 堆栈信息
private String t = "error";
}
package io.terminus.monitor.model;
import org.litepal.crud.DataSupport;
/**
* User : yh
* Date : 17/2/21
*/
public class EventModel extends BaseModel{
private String eventName;
public String getXp() {
return xp;
}
public void setXp(String xp) {
this.xp = xp;
}
public String getX() {
return x;
}
public void setY(String y) {
this.y = y;
}
public String getEventName() {
return eventName;
}
public void setEventName(String eventName) {
this.eventName = eventName;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
private String xp;
private String x;
private String y;
private String t = "event";
}
package io.terminus.monitor.model;
/**
* User : yh
* Date : 17/2/21
*/
public class PageModel extends BaseModel{
public String getDt() {
return dt;
}
public void setDt(String dt) {
this.dt = dt;
}
public String getTp() {
return tp;
}
public void setTp(String tp) {
this.tp = tp;
}
public long getSt() {
return st;
}
public void setSt(long st) {
this.st = st;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
public String getDr() {
return dr;
}
public void setDr(String dr) {
this.dr = dr;
}
private String dt; // 界面标题
private long st; //记录页面开始时间
private String tp; // 页面停留时间
private String dr; // 上一个页面信息
private String t = "document";
}
package io.terminus.monitor.model;
/**
* User : yh
* Date : 17/2/28
*/
public class PerformanceModel extends BaseModel{
// public double getFps() {
// return fps;
// }
//
// public void setFps(double fps) {
// this.fps = fps;
// }
//
// public double getCpu() {
// return cpu;
// }
//
// public void setCpu(double cpu) {
// this.cpu = cpu;
// }
//
// public double getMem() {
// return mem;
// }
//
// public void setMem(double mem) {
// this.mem = mem;
// }
//
// public double getHang() {
// return hang;
// }
//
// public void setHang(double hang) {
// this.hang = hang;
// }
//
// public double getNetflow() {
// return netflow;
// }
//
// public void setNetflow(double netflow) {
// this.netflow = netflow;
// }
public String getNt() {
return nt;
}
public void setNt(String nt) {
this.nt = nt;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
// private double fps;
// private double cpu;
// private double mem;
// private double hang; //延迟
// private double netflow;
private String nt;
private String t = "timing";
}
package io.terminus.monitor.model;
/**
* Created by ZYWu on 2017/7/4.
*/
/**
* User : ZYWu
* Date : 2017/7/4
*/
public class RequestModel extends BaseModel{
public String getTt() {
return tt;
}
public void setTt(String tt) {
this.tt = tt;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getSt() {
return st;
}
public void setSt(String st) {
this.st = st;
}
public String getMe() {
return me;
}
public void setMe(String me) {
this.me = me;
}
public String getReq() {
return req;
}
public void setReq(String req) {
this.req = req;
}
public String getRes() {
return res;
}
public void setRes(String res) {
this.res = res;
}
public String getT() {
return t;
}
public void setT(String t) {
this.t = t;
}
private String tt; // 响应时间
private String url; // 请求路径
private String st; // 响应状态
private String me; // 请求方法
private String req; // 请求体大小
private String res; // 响应体大小
private String t = "request";
}
package io.terminus.monitor.module;
/**
* User : yh
* Date : 17/2/20
*/
import android.content.Context;
import android.widget.Toast;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import io.terminus.monitor.RNMobClickAgent;
import io.terminus.monitor.model.ErrorModel;
import io.terminus.monitor.util.ToolUtil;
/**
* 异常捕获
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler{
private static CrashHandler mHandler;
private Context mContext;
private Thread.UncaughtExceptionHandler mDefaultHandler;
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
private CrashHandler(){
}
public static CrashHandler getInstance(){
if(mHandler == null){
mHandler = new CrashHandler();
}
return mHandler;
}
public void init(Context context){
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if(mDefaultHandler != null) {
handleException(ex);
}
try{
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
private void handleException(Throwable ex){
ErrorModel model = new ErrorModel();
// model.setCreateTime(ToolUtil.getNowTime());
model.setErm(ex.getMessage());
// model.setDate(ToolUtil.getNowTime());
model.setSta(getStrackTrace(ex.getStackTrace()));
System.out.println(getStrackTrace(ex.getStackTrace()));
RNMobClickAgent.getInstance().onEvent(model);
}
public static String getStrackTrace(StackTraceElement[] trace){
if(trace == null || trace.length < 1){
return "";
}
StringBuffer buf = new StringBuffer("");
for(int count = 0; count < trace.length; ++count){
buf.append(trace[count].toString());
buf.append("\n");
}
return buf.toString();
}
}
package io.terminus.monitor.module;
import android.content.Context;
import org.litepal.LitePal;
import org.litepal.crud.DataSupport;
import java.util.ArrayList;
import java.util.List;
import io.terminus.monitor.model.BaseModel;
/**
* User : yh
* Date : 17/2/21
*/
public class LitePalHelper<T extends BaseModel> {
private static LitePalHelper helper;
private List<Class<T> > classList;
private LitePalHelper(){
classList = new ArrayList<>();
}
public void init(Context mContext){
LitePal.initialize(mContext);
}
public void LogModelRegist(Class<T> t){
if(classList.contains(t)){
return;
}
classList.add(t);
}
public static LitePalHelper getInstance(){
if(helper == null){
helper = new LitePalHelper();
}
return helper;
}
public void save(T t){
t.save();
}
public T getData(Class<T> t){
return DataSupport.find(t,1);
}
public void deleteData(Class<T> t,long id){
DataSupport.delete(t,id);
}
public List<T> getAllData(){
List<T> all = new ArrayList<>();
for(Class<T> cls : classList){
all.addAll(DataSupport.findAll(cls));
}
return all;
}
public int count(){
int count = 0;
for(Class<T> cls : classList){
count += DataSupport.count(cls);
}
return count;
}
}
package io.terminus.monitor.module;
import android.content.Context;
import android.view.Choreographer;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.modules.debug.FpsDebugFrameCallback;
import io.terminus.monitor.model.PerformanceModel;
import io.terminus.monitor.util.ToolUtil;
/**
* User : yh
* Date : 17/2/22
*/
public class PerFormanceTool {
private static PerFormanceTool tool;
private double fps;
private double jsfps;
private double cpu;
private double memory;
private PerFormanceTool(){
}
public static PerFormanceTool getInstance(){
if(tool == null){
tool = new PerFormanceTool();
}
return tool;
}
public void init(final ReactContext mContext){
// mFrameCallback = new FpsDebugFrameCallback(Choreographer.getInstance(), mContext);
// mFrameCallback.start();
}
public void pageLoadTime(String pageName,String pageTime) {
PerformanceModel model = new PerformanceModel();
model.setNt(pageTime);
model.setDp(pageName);
UploadManager.getInstance().addTask(model);
}
public void setFPS(double fps,double jsfps){
this.fps = fps;
this.jsfps = jsfps;
this.cpu = ToolUtil.getProcessCpuRate();
this.memory = Runtime.getRuntime().totalMemory()/(1024*1024.0);
PerformanceModel model = new PerformanceModel();
// model.setFps(fps);
// model.setCpu(cpu);
// model.setMem( memory);
UploadManager.getInstance().addTask(model);
}
}
package io.terminus.monitor.module;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.text.TextUtils;
import android.widget.Toast;
import com.google.gson.Gson;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import com.loopj.android.http.ResponseHandlerInterface;
import com.loopj.android.http.SyncHttpClient;
import com.loopj.android.http.PreemptiveAuthorizationHttpRequestInterceptor;
import java.util.ArrayList;
import io.terminus.monitor.AnalyticsConfig;
import io.terminus.monitor.RNMobClickAgent;
import io.terminus.monitor.model.BaseModel;
import io.terminus.monitor.model.DeviceInfo;
import io.terminus.monitor.model.Enum.NetInfoEnum;
import io.terminus.monitor.model.Enum.UploadModel;
import io.terminus.monitor.util.DeviceIDUtil;
import io.terminus.monitor.util.DeviceUtil;
import io.terminus.monitor.util.ToolUtil;
/**
* User : yh
* Date : 17/2/21
*/
public class UploadManager {
private static UploadManager manager;
private ArrayList<BaseModel> taskQueue;
private TaskThread taskThread;
private ConnectionChangeReceiver receiver;
private NetInfoEnum netState;
private SyncHttpClient netClient;
private final int LIMIT = 20;
private Context cusmcontext;
private UploadManager(){
taskQueue = new ArrayList<BaseModel>();
taskThread = new TaskThread();
taskThread.start();
}
public static UploadManager getInstance(){
if(manager == null){
manager = new UploadManager();
}
return manager;
}
public void init(Context mcontext){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
receiver = new ConnectionChangeReceiver();
mcontext.registerReceiver(receiver,intentFilter);
netState = DeviceUtil.getNetWorkInfo(mcontext);
netClient = new SyncHttpClient();
netClient.addHeader("User-Agent","Android");
netClient.addHeader("Referer","home_page");
cusmcontext = mcontext;
synchronized (taskQueue) {
taskQueue.addAll(LitePalHelper.getInstance().getAllData());
taskQueue.notifyAll();
}
}
public void LoadLogFromDB(){
synchronized (taskQueue) {
taskQueue.addAll(LitePalHelper.getInstance().getAllData());
if(!taskQueue.isEmpty()){
taskQueue.notifyAll();
}
}
}
public void addTask(BaseModel model){
LitePalHelper.getInstance().save(applyBaseParam(model));
if(AnalyticsConfig.getUploadModel() == UploadModel.REAL_TIME){
synchronized (taskQueue) {
taskQueue.addAll(LitePalHelper.getInstance().getAllData());
taskQueue.notifyAll();
}
}else if((AnalyticsConfig.getUploadModel() == UploadModel.WIFI_LIMIT || AnalyticsConfig.getUploadModel() == UploadModel.REAL_TIME_WIFI)&& netState == NetInfoEnum.WIFI){
synchronized (taskQueue){
if(LitePalHelper.getInstance().count() >= LIMIT){
taskQueue.addAll(LitePalHelper.getInstance().getAllData());
taskQueue.notifyAll();
}
}
}
}
public void addDeviceTask(BaseModel model){
LitePalHelper.getInstance().save(applyBaseParam(model));
synchronized (taskQueue) {
taskQueue.addAll(LitePalHelper.getInstance().getAllData());
taskQueue.notifyAll();
}
}
public BaseModel applyBaseParam(BaseModel model){
model.setDate(ToolUtil.getNowTime());
model.setNs(DeviceUtil.getNetWorkInfo(cusmcontext).getStatus());
model.setAv(DeviceUtil.getAppVersion(cusmcontext));
model.setUid(AnalyticsConfig.getUserId());
model.setAk(AnalyticsConfig.getAppKey());
DeviceIDUtil DeviceID = new DeviceIDUtil(cusmcontext);
model.setVid(DeviceID.getDeviceUUId().toString());
model.setCid(DeviceID.getDeviceId());
model.setDh(cusmcontext.getPackageName());
model.setBr(Build.MODEL);
model.setOsv(Build.VERSION.RELEASE);
model.setMd(Build.MODEL);
String osName = Build.MANUFACTURER + " android";
model.setOsn(osName);
model.setGps(DeviceUtil.locationInfo(cusmcontext));
model.setUa("Android");
return model;
}
private class TaskThread extends Thread{
@Override
public void run() {
while (true){
synchronized (taskQueue){
if(taskQueue.isEmpty()){
try {
taskQueue.wait();
}catch (Exception e){
}
}else{
RequestParams params = new RequestParams();
params.put("ak",AnalyticsConfig.getAppKey());
params.put("cid",AnalyticsConfig.getDeviceId());
params.put("ip",DeviceUtil.getNetIp());
params.put("uid",AnalyticsConfig.getUserId());
for(BaseModel model : taskQueue){
LitePalHelper.getInstance().deleteData(model.getClass(),model.getId());
params.add("data",ToolUtil.toRequestParams(model).toString());
}
taskQueue.clear();
netClient.post(AnalyticsConfig.getDomain(), params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, org.apache.http.Header[] headers, byte[] responseBody) {
}
@Override
public void onFailure(int statusCode, org.apache.http.Header[] headers, byte[] responseBody, Throwable error) {
}
});
}
}
}
}
}
public class ConnectionChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
netState = DeviceUtil.getNetWorkInfo(context);
// if(netState == NetInfoEnum.WIFI && AnalyticsConfig.getUploadModel() == UploadModel.REAL_TIME){
// LoadLogFromDB();
// }
}
}
}
package io.terminus.monitor.util;
/**
* Created by ZYWu on 2017/6/22.
*/
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
public class DeviceIDUtil {
protected static final String PREFS_FILE = "device_id.xml";
protected static final String PREFS_DEVICE_ID = "device_id";
protected static volatile UUID uuid;
public DeviceIDUtil(Context context) {
this.createUUID(context);
}
private void createUUID(Context context) {
if(uuid == null) {
Class var2 = DeviceIDUtil.class;
synchronized(DeviceIDUtil.class) {
if(uuid == null) {
SharedPreferences prefs = context.getSharedPreferences("device_id.xml", 0);
String id = prefs.getString("device_id", (String)null);
if(id != null) {
uuid = UUID.fromString(id);
} else {
String androidId = Settings.Secure.getString(context.getContentResolver(), "android_id");
try {
if(!"9774d56d682e549c".equals(androidId)) {
uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));
} else {
String e = ((TelephonyManager)context.getSystemService("phone")).getDeviceId();
uuid = e != null?UUID.nameUUIDFromBytes(e.getBytes("utf8")):UUID.randomUUID();
}
} catch (UnsupportedEncodingException var8) {
throw new RuntimeException(var8);
}
prefs.edit().putString("device_id", uuid.toString()).commit();
}
}
}
}
}
public UUID getDeviceUUId() {
return uuid;
}
public String getDeviceId() {
return this.getDeviceUUId().toString();
}
}
package io.terminus.monitor.util;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.StatFs;
import android.telephony.TelephonyManager;
import android.text.format.Formatter;
import android.util.DisplayMetrics;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import io.terminus.monitor.model.DeviceInfo;
import io.terminus.monitor.model.Enum.NetInfoEnum;
import io.terminus.monitor.util.DeviceIDUtil;
import android.os.Environment;
import static android.content.Context.TELEPHONY_SERVICE;
/**
* User : yh
* Date : 17/2/20
*/
public class DeviceUtil {
/**
* 获取设备信息
* @param mContext
* @return
*/
public static DeviceInfo getDeviceInfo(Context mContext){
DeviceInfo info = new DeviceInfo();
DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
info.setSr(dm.widthPixels+"*"+dm.heightPixels);
info.setCh(getChannel(mContext));
info.setJb((ToolUtil.root() ? 1 : 0));
File dataFileDir=Environment.getDataDirectory();
File path = Environment.getExternalStorageDirectory();
info.setRom(getMemoryInfo(dataFileDir,mContext));
info.setMem(getTotalRam(mContext));
info.setSd(getMemoryInfo(path,mContext));
info.setCpu(Build.CPU_ABI);
info.setSdk(Build.VERSION.RELEASE);
return info;
}
//渠道信息
public static String getChannel(Context mContext){
try{
ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(), PackageManager.GET_META_DATA);
return info.metaData.getString("CHANNEL");
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public static String getAppVersion(Context mContext){
try {
PackageInfo info = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(),0);
return info.versionName;
}catch (Exception e) {
//
}
return null;
}
public static NetInfoEnum getNetWorkInfo(Context mContext){
NetworkInfo networkInfo = ((ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
// networkInfo.
if(networkInfo == null || !networkInfo.isConnected()){
return NetInfoEnum.OFFLINE;
}
if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
return NetInfoEnum.WIFI;
}
if(networkInfo.getType() != ConnectivityManager.TYPE_MOBILE){
return NetInfoEnum.UNKNOWN;
}
String subTypeName = networkInfo.getSubtypeName();
int subType = networkInfo.getSubtype();
NetInfoEnum type = NetInfoEnum.UNKNOWN;
switch (subType){
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN: //api<8 : replace by 11
type = NetInfoEnum.G2;
break;
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B: //api<9 : replace by 14
case TelephonyManager.NETWORK_TYPE_EHRPD: //api<11 : replace by 12
case TelephonyManager.NETWORK_TYPE_HSPAP: //api<13 : replace by 15
type = NetInfoEnum.G3;
break;
case TelephonyManager.NETWORK_TYPE_LTE: //api<11 : replace by 13
type = NetInfoEnum.G4;
break;
default:
if(subTypeName.equalsIgnoreCase("TD-SCDMA") || subTypeName.equalsIgnoreCase("WCDMA") || subTypeName.equalsIgnoreCase("CDMA2000")){
type = NetInfoEnum.G3;
}
break;
}
return type;
}
public static String locationInfo(Context mContext){
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
List<String> providers = locationManager.getProviders(true);
String locationProvider;
if(providers.contains(LocationManager.GPS_PROVIDER)){
//如果是GPS
locationProvider = LocationManager.GPS_PROVIDER;
}else if(providers.contains(LocationManager.NETWORK_PROVIDER)){
//如果是Network
locationProvider = LocationManager.NETWORK_PROVIDER;
}else{
return null;
}
Location location = locationManager.getLastKnownLocation(locationProvider);
if(location == null){
return null;
}
return location.getLatitude()+","+location.getLongitude();
}
public static String getDeviceId(Context mContext){
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(TELEPHONY_SERVICE);
final String tmDevice;
tmDevice = "" + new DeviceIDUtil(mContext).getDeviceId();
return tmDevice;
}
public static String getNetIp() {
URL infoUrl = null;
InputStream inStream = null;
String ipLine = "";
HttpURLConnection httpConnection = null;
try {
infoUrl = new URL("http://pv.sohu.com/cityjson?ie=utf-8");
URLConnection connection = infoUrl.openConnection();
httpConnection = (HttpURLConnection) connection;
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
inStream = httpConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "utf-8"));
StringBuilder strber = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null){
strber.append(line + "\n");
}
Pattern pattern = Pattern
.compile("((?:(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d)))\\.){3}(?:25[0-5]|2[0-4]\\d|((1\\d{2})|([1-9]?\\d))))");
Matcher matcher = pattern.matcher(strber.toString());
if (matcher.find()) {
ipLine = matcher.group();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStream.close();
httpConnection.disconnect();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return ipLine;
}
public static String getMemoryInfo(File path,Context mContext) {
long blockSize;
long totalBlockCount;
StatFs stat = new StatFs(path.getPath());
long blockSiza= stat.getBlockSize();
long totalBlocks = stat.getBlockCount();
//检测系统版本
if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.JELLY_BEAN_MR2){
//获取每个扇区的大小
blockSize = stat.getBlockSizeLong();
//获取总共有多少扇区
totalBlockCount=stat.getBlockCountLong();
}else{
blockSize=stat.getBlockSize();
totalBlockCount=stat.getBlockCount();
}
// 磁盘总大小
String totalMemory =Formatter.formatFileSize(mContext, blockSize*totalBlockCount);
return totalMemory;
}
/** * 获取SD卡信息 * * @return SDCardInfo */
/** * 判断SD卡是否可用 * * @return true : 可用<br>false : 不可用 */
public static boolean isSDCardEnable() {
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
// 获取内存大小
public static String getTotalRam(Context context){
String path = "/proc/meminfo";
String firstLine = null;
int totalRam = 0 ;
try{
FileReader fileReader = new FileReader(path);
BufferedReader br = new BufferedReader(fileReader,8192);
firstLine = br.readLine().split("\\s+")[1];
br.close();
}catch (Exception e){
e.printStackTrace();
}
if(firstLine != null){
totalRam = (int)Math.ceil((new Float(Float.valueOf(firstLine) / (1024 * 1024)).doubleValue()));
}
return totalRam + "GB";//返回1GB/2GB/3GB/4GB
}
public static String getCpuName() {
try {
FileReader fr = new FileReader("/proc/cpuinfo");
BufferedReader br = new BufferedReader(fr);
String text = br.readLine();
String[] array = text.split(":\\s+", 2);
for (int i = 0; i < array.length; i++) {
}
return array[1];
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
package io.terminus.monitor.util;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.text.format.DateFormat;
import com.google.gson.Gson;
import com.loopj.android.http.RequestParams;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import io.terminus.monitor.AnalyticsConfig;
import io.terminus.monitor.model.Enum.NetInfoEnum;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
/**
* User : yh
* Date : 17/2/20
*/
public class ToolUtil {
public static boolean isDebug(Context mContext){
ApplicationInfo info = mContext.getApplicationInfo();
if((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0){
return true;
}
return false;
}
public static boolean isWifi(Context mContext){
if(DeviceUtil.getNetWorkInfo(mContext) == NetInfoEnum.WIFI){
return true;
}
return false;
}
public static boolean root(){
try{
if(!new File("/system/bin/su").exists() && !new File("/system/xbin/su").exists()){
return false;
}
return true;
}catch (Exception e){
}
return false;
}
/**
*
* @return yyyy-MM-dd HH:mm:ss
*/
public static String getNowTime(){
long time= System.currentTimeMillis();
return String.valueOf(time);
}
/**
*
* @return time
*/
public static long getNowTimeMillis(){
Date time = new Date(System.currentTimeMillis());
return time.getTime();
}
public static float getProcessCpuRate()
{
float totalCpuTime1 = getTotalCpuTime();
float processCpuTime1 = getAppCpuTime();
try
{
Thread.sleep(360);
}
catch (Exception e)
{
}
float totalCpuTime2 = getTotalCpuTime();
float processCpuTime2 = getAppCpuTime();
float cpuRate = 100 * (processCpuTime2 - processCpuTime1)
/ (totalCpuTime2 - totalCpuTime1);
return cpuRate;
}
private static long getTotalCpuTime()
{ // 获取系统总CPU使用时间
String[] cpuInfos = null;
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/stat")), 1000);
String load = reader.readLine();
reader.close();
cpuInfos = load.split(" ");
}
catch (IOException ex)
{
ex.printStackTrace();
}
long totalCpu = Long.parseLong(cpuInfos[2])
+ Long.parseLong(cpuInfos[3]) + Long.parseLong(cpuInfos[4])
+ Long.parseLong(cpuInfos[6]) + Long.parseLong(cpuInfos[5])
+ Long.parseLong(cpuInfos[7]) + Long.parseLong(cpuInfos[8]);
return totalCpu;
}
private static long getAppCpuTime()
{ // 获取应用占用的CPU时间
String[] cpuInfos = null;
try
{
int pid = android.os.Process.myPid();
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/" + pid + "/stat")), 1000);
String load = reader.readLine();
reader.close();
cpuInfos = load.split(" ");
}
catch (IOException ex)
{
ex.printStackTrace();
}
long appCpuTime = Long.parseLong(cpuInfos[13])
+ Long.parseLong(cpuInfos[14]) + Long.parseLong(cpuInfos[15])
+ Long.parseLong(cpuInfos[16]);
return appCpuTime;
}
public static RequestParams toRequestParams(Object obj){
RequestParams params = new RequestParams();
Method[] methods = obj.getClass().getMethods();
try {
for (Method m : methods) {
if (m.getName().startsWith("get") && !m.getName().startsWith("getClass") && !m.getName().equals("getId")) {
if(m.invoke(obj) == null){continue;}
String value = String.valueOf((Object) m.invoke(obj));
value = URLEncoder.encode(value,"UTF-8");
if(value != null){
String name = m.getName().substring(3, 4).toLowerCase() + m.getName().substring(4);
params.put(name,value);
}
}
}
}catch (Exception e){
e.printStackTrace();
}
return params;
}
}
import React from 'react'
import { NativeModules } from 'react-native';
import * as MonitorType from './MonitorType';
const { RNMonitor } = NativeModules;
var Monitor = {
/**
* 统计初始化,
* appkey 系统分配的
* UploadModel 上传方式 ; REAL_TIME : 实时上传 READL_TIME_WIFI :WiFi下实时上传 WIFI : WiFi下首次启动上传
*/
init(appkey,UploadModel){
RNMonitor.init(appkey,UploadModel);
// require('ErrorUtils').setGlobalHandler((error)=>{
// RNMonitor.onError({erm:error.message,sta:error.stack})
// })
// this.getNowFormatDate = this.getNowFormatDate.bind(this);
},
/***
* 用户统计
*/
onSignIn(userId){
RNMonitor.onSignIn(userId);
},
/**
* event 数据结构
* {
* eventPageName 事件所在页面
* eventId, 事件id
* createTime, 事件发生时间 //可不传
* eventName, 事件名称
* extra,
* }
*/
onCusEvent(obj){
if(!obj){
throw new Error("event info should not be null")
return;
}
var keys = ["eventId","eventName","eventPageName","extra","createTime"];
let event = {};
keys.map((key,index)=>{
if(key === 'eventId' && !obj[key]){
throw new Error('eventId should not be null');
return;
}
event[key] = obj[key];
})
if(event.createTime === undefined){
event['createTime'] = this.getNowFormatDate();
}
RNMonitor.onCusEvent(event);
},
/**
* 组件 willmount 方法中调用
* pageObj 为当前页面或组件对象(this),该名称必须与onPageEnd的参数名称保持一致,否则无法正确统计页面停留时间
*/
onPageStart(pageName,lastPage){
// const pageName = pageObj &&
// pageObj._reactInternalInstance &&
// pageObj._reactInternalInstance._currentElement &&
// pageObj._reactInternalInstance._currentElement.type &&
// pageObj._reactInternalInstance._currentElement.type.name
if(pageName){
RNMonitor.onPageStart(pageName,lastPage)
}
},
/**
* pageObj ,或者 页面发生跳转的时候调用
*/
onPageEnd(pageName){
// const pageName = pageObj &&
// pageObj._reactInternalInstance &&
// pageObj._reactInternalInstance._currentElement &&
// pageObj._reactInternalInstance._currentElement.type &&
// pageObj._reactInternalInstance._currentElement.type.name
if(pageName){
RNMonitor.onPageEnd(pageName)
}
},
/**
* pageObj ,或者 页面发生跳转的时候调用
*/
pageLoad(pageName,loadTime){
if(pageName && loadTime ){
RNMonitor.pageLoadTime(pageName,loadTime)
}
},
/* requestParam:中必须包含参数:
*
请求响应时间 tt;
请求路径 url;
响应状态 st;
请求方法 me;
请求体大小 req;
响应体大小 res;
*/
sendRequest(requestParam){
if(requestParam){
RNMonitor.sendRequest(requestParam)
}
},
/* eventParam:中必须包含参数:
*
target xpath xp;
事件坐标x x;
事件坐标y y;
*/
onEvent(eventParam){
if(eventParam){
RNMonitor.event(eventParam)
}
},
/* errorParam:中必须包含参数:
*
错误日志 erm;
堆栈信息 sta;
*/
onError(errorParam){
if(errorParam){
RNMonitor.onError(errorParam)
}
},
getNowFormatDate(){
var date = new Date();
var seperator1 = "/";
var seperator2 = ":";
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
}
export { Monitor,MonitorType};
#import "RCTBridgeModule.h"
@interface RNMonitor : NSObject <RCTBridgeModule>
@end
#import "RNMonitor.h"
#import "RNMonitorConfig.h"
#import "RNCusEventManager.h"
#import "RNPageManager.h"
#import "RNRequestManager.h"
#import "RNPerformanceManager.h"
#import "RNEventManager.h"
#import "RNLogManager.h"
@implementation RNMonitor
- (NSDictionary *)constantsToExport
{
return @{ @"REAL_TIME": @"1", @"REAL_TIME_WIFI": @"2",@"WIFI":@"3"};
}
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE(RNMonitor)
RCT_EXPORT_METHOD(init:(NSString*)appkey model:(NSString*)uploadModel){
NSInteger type = uploadModel.integerValue;
[[RNMonitorConfig shareInstance] startMonitorWithAppKey:appkey];
switch (type) {
case 1:
[[RNMonitorConfig shareInstance] setType:RNUploadTypeRealTime];
break;
case 2:
[[RNMonitorConfig shareInstance] setType:RNUploadTypeWifiLimit];
break;
case 3:
[[RNMonitorConfig shareInstance] setType:RNUploadTypeActivate];
break;
default:
break;
}
}
RCT_EXPORT_METHOD(onSignIn:(NSString*)uid){
[[RNMonitorConfig shareInstance] setUid:uid];
}
RCT_EXPORT_METHOD(onCusEvent:(NSDictionary*)event){
NSArray*keys = @[@"eventId",@"eventName",@"eventPageName",@"extra"];
NSMutableArray *values = [NSMutableArray arrayWithCapacity:4];
for (NSString *key in keys) {
[event.allKeys containsObject:key]?[values addObject:event[key]]: [values addObject:@""];
}
[[RNCusEventManager shareInstance] event:values[0]
eventName:values[1]
pageName:values[2]
extra:values[3]];
}
RCT_EXPORT_METHOD(onPageStart:(NSString*)pageName lastPage:(NSString*)lastPage){
[[RNPageManager shareInstance] startPageView:pageName lastPage:lastPage];
}
RCT_EXPORT_METHOD(onPageEnd:(NSString*)pageName){
[[RNPageManager shareInstance] endPageView:pageName];
}
RCT_EXPORT_METHOD(pageLoadTime:(NSString*)pageName pageTime:(NSString*)time){
[[RNPerformanceManager shareInstance] pageLoadTime:pageName
time:time];
}
/* requestParam:中必须包含参数:
*
请求响应时间 tt;
请求路径 url;
响应状态 st;
请求方法 me;
请求体大小 req;
响应体大小 res;
*/
RCT_EXPORT_METHOD(sendRequest:(NSDictionary*)requestParam){
[[RNRequestManager shareInstance] sendRequest:requestParam];
}
/* eventParam:中必须包含参数:
*
target xpath xp;
事件坐标x x;
事件坐标y y;
*/
RCT_EXPORT_METHOD(event:(NSDictionary*)eventParam){
[[RNEventManager shareInstance] event:eventParam];
}
/* errorParam:中必须包含参数:
*
错误日志 erm;
堆栈信息 sta;
*/
RCT_EXPORT_METHOD(onError:(NSDictionary*)errorParam){
[[RNLogManager shareInstance] handerReactNativeError:errorParam];
}
@end
//
// RNMonitorConfig.h
// RNMonitor
//
// Created by zhiyu on 17/2/23.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString *KModelName;
extern NSString *KDeviceEntityName;
extern NSString *KEventEntityName;
extern NSString *KPageEntityName;
extern NSString *KLogEntityName;
extern NSString *KPerformanceEntityName;
extern NSString *KRequestEntityName;
typedef NS_ENUM(NSInteger, RNUploadType) {
RNUploadTypeWifiLimit = 1, //wifi+limit
RNUploadTypeActivate, // 启动
RNUploadTypeRealTime // 实时
};
@interface RNMonitorConfig : NSObject
@property(nonatomic,assign)RNUploadType type;
@property(nonatomic,copy)NSString*baseURL;
@property(nonatomic,copy)NSString*appKey;
@property(nonatomic,assign)NSInteger uploadLimit;
@property(nonatomic,copy)NSString* uid;
@property(nonatomic,assign)BOOL Debug;
+ (instancetype)shareInstance;
- (void)startMonitorWithAppKey:(NSString*)appKey ;
@end
//
// RNMonitorConfig.m
// RNMonitor
//
// Created by zhiyu on 17/2/23.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNMonitorConfig.h"
#import "RNPageManager.h"
#import "RNCusEventManager.h"
#import "RNDeviceManager.h"
#import "RNLogManager.h"
#import "RNPerformanceManager.h"
#import "RNRequestManager.h"
#import "RNDevice.h"
#import "Reachability.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
NSString * KModelName = @"RNMonitor";
NSString * KDeviceEntityName = @"device";
NSString * KEventEntityName = @"event";
NSString * KPageEntityName = @"document";
NSString * KLogEntityName = @"error";
NSString * KPerformanceEntityName = @"timing";
NSString * KRequestEntityName = @"request";
@implementation RNMonitorConfig{
Reachability *_reachability;
}
+ (instancetype)shareInstance {
static RNMonitorConfig *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
_type = RNUploadTypeActivate;
_baseURL = @"https://analytics.terminus.io/collect";
_uploadLimit = 10;
_Debug = YES;
// [NSURLProtocol registerClass:[RNFlow class]];
}
return self;
}
- (void)startMonitorWithAppKey:(NSString *)appKey {
_appKey = appKey;
[self startMonitor];
if (_type == RNUploadTypeActivate) {
[self uploadAllLastMessage:NO];
}else if (_type == RNUploadTypeWifiLimit){
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(netWorkStatusChange) name:kReachabilityChangedNotification object:nil];
_reachability = [Reachability reachabilityForInternetConnection];
[_reachability startNotifier];
[self netWorkStatusChange];
}
}
- (void)startMonitor{
[RNFMDB shareDatabase:KModelName];
[[RNDeviceManager shareInstance] start];
[[RNLogManager shareInstance] start];
[[RNPageManager shareInstance] start];
[[RNPerformanceManager shareInstance] start];
[[RNRequestManager shareInstance] start];
// [[RNCusEventManager shareInstance] start];
}
- (void)uploadAllLastMessage:(BOOL)Limit{
[RNMonitorUploadManager uploadMonitor:KDeviceEntityName];
[RNMonitorUploadManager uploadMonitor:KLogEntityName];
[RNMonitorUploadManager uploadMonitor:KPerformanceEntityName];
[RNMonitorUploadManager uploadMonitor:KRequestEntityName];
[RNMonitorUploadManager uploadMonitor:KPageEntityName];
// [RNMonitorUploadManager uploadMonitor:KEventEntityName];
}
- (void)netWorkStatusChange{
if([_reachability currentReachabilityStatus] == ReachableViaWiFi){
[self uploadAllLastMessage:YES];
}
}
@end
//
// RNMonitorUploadManager.h
// RNMonitor
//
// Created by zhiyu on 17/3/13.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@class RNParamDO;
@interface RNMonitorUploadManager : NSObject
//+ (void)uploadLastMonitor:(BOOL)limit path:(NSString*)path;
//+ (void)upload:(NSArray*)dataArray path:(NSString*)path;
//+ (void)checkUpload:(id)data path:(NSString*)path;
+ (void)uploadMonitor:(NSString *)topic;
+ (void)applyBaseParam:(NSString *)topic
pageName:(NSString*)pageName
data:(RNParamDO*)paramDO;
@end
//
// RNMonitorUploadManager.m
// RNMonitor
//
// Created by zhiyu on 17/3/13.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNMonitorUploadManager.h"
#import "RNDataManager.h"
#import "RNUtil.h"
#import "RNMonitorConfig.h"
#import "RNUpdateService.h"
#import "RNDevice.h"
#import "RNParamDO.h"
#import "RNFMDB.h"
#import "NSObject+RNMIU_ToDictionary.h"
#import "RNLocationManager.h"
@implementation RNMonitorUploadManager
+ (void)uploadMonitor:(NSString *)topic
{
NSArray *array = [[RNFMDB shareDatabase] jq_lookupTable:topic
dicOrModel:[NSDictionary class]
whereFormat:@"where t = '%@'",topic];
if ([RNMonitorConfig shareInstance].uploadLimit && (array.count >= [RNMonitorConfig shareInstance].uploadLimit)) {
NSArray *newArray = [self recombinationArray:array length:[RNMonitorConfig shareInstance].uploadLimit];
[newArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[RNMonitorUploadManager upload:obj table:topic];
}];
}else if(![RNMonitorConfig shareInstance].uploadLimit){
[RNMonitorUploadManager upload:array table:topic];
}
}
+ (void)applyBaseParam:(NSString *)topic
pageName:(NSString*)pageName
data:(RNParamDO*)paramDO {
paramDO.date = [RNUtil getCurrentTime];
paramDO.ns = [RNDevice iphoneNetState];
paramDO.av = [RNDevice appVersion];
paramDO.uid = [RNMonitorConfig shareInstance].uid;
paramDO.ak = [RNMonitorConfig shareInstance].appKey;
paramDO.dp = pageName;
paramDO.dh = [RNDevice bundleId];
paramDO.cid = [RNDevice deviceId];
paramDO.br =@"iphone";
paramDO.md = [RNDevice iphoneType];
paramDO.osn = @"iOS";
paramDO.osv = [RNDevice iphoneSystemVersion];
paramDO.ua = @"IOS";
paramDO.vid = [RNDevice deviceId];
paramDO.t = topic;
if([RNLocationManager shareInstance].location){
paramDO.gps = [RNLocationManager shareInstance] .location;
[RNMonitorUploadManager checkUploadForENV:paramDO table:topic];
}else{
[[RNLocationManager shareInstance] startLocation:^(NSString *location, NSError *error) {
if (location) {
paramDO.gps = location;
}
[RNMonitorUploadManager checkUploadForENV:paramDO table:topic];
}];
}
}
+ (void)checkUploadForENV:(id)data table:(NSString *)tableName{
if ([tableName isEqualToString:KDeviceEntityName]) {
[self upload:@[[data RNMIU_ToDictionary]] table:tableName];
return ;
}
if([RNMonitorConfig shareInstance].Debug){
#if DEBUG
[[RNFMDB shareDatabase] jq_insertTable:tableName dicOrModel:data];
[self upload:@[[data RNMIU_ToDictionary]] table:tableName];
#else
[self checkUpload:data table:tableName];
#endif
}else{
[self checkUpload:data table:tableName];
}
}
+ (void)checkUpload:(id)data table:(NSString *)tableName{
if([RNMonitorConfig shareInstance].type == RNUploadTypeRealTime){
[[RNFMDB shareDatabase] jq_insertTable:tableName dicOrModel:data];
[self upload:@[[data RNMIU_ToDictionary]] table:tableName];
}else if([RNMonitorConfig shareInstance].type == RNUploadTypeWifiLimit ){
[[RNFMDB shareDatabase] jq_insertTable:tableName dicOrModel:data];
![[RNDevice iphoneNetState] isEqualToString:@"wifi"]?: [self uploadMonitor:tableName];
}else if([RNMonitorConfig shareInstance].type == RNUploadTypeActivate){
[[RNFMDB shareDatabase] jq_insertTable:tableName dicOrModel:data];
}
}
// 根据数据上传
+ (void)upload:(id)monData table:(NSString *)tableName{
if (!monData || [(NSArray*)monData count] ==0) {
return;
}
id param =@{@"cid":[RNUtil deviceId],
@"ak":[RNMonitorConfig shareInstance].appKey?:@"",
@"uid":[RNMonitorConfig shareInstance].uid?:@"",
@"data":monData};
[RNUpdateService POST:[RNMonitorConfig shareInstance].baseURL
parameters:param
resultBlock:^(BOOL success, id data, NSError *error) {
if (success) {
[monData enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[[RNFMDB shareDatabase] jq_deleteTable:tableName whereFormat:@"where date = '%@'",obj[@"date"]];
}];
}
}];
}
+ (NSArray *)recombinationArray:(NSArray*)array length:(NSInteger)subSize {
unsigned long count = array.count % subSize == 0 ? (array.count / subSize) : (array.count / subSize + 1);
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (int i = 0; i < count; i ++) {
int index = i * subSize;
NSMutableArray *arr1 = [[NSMutableArray alloc] init];
[arr1 removeAllObjects];
int j = index;
while (j < subSize*(i + 1) && j < array.count) {
[arr1 addObject:[array objectAtIndex:j]];
j += 1;
}
[arr addObject:[arr1 copy]];
}
return [arr copy];
}
@end
//
// LPEventManager.h
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString *KReceiveEventNotification;
@interface RNCusEventManager : NSObject
@property(nonatomic,copy) NSString *eventPath;
+ (instancetype)shareInstance;
- (void)start;
- (void)uploadLastEvent:(BOOL)limit;
/**
*eventId 注册的事件ID
*eventName 注册的事件名称
*eventPageName 页面名称
*extra 额外参数
*/
- (void)event:(NSString *)eventId
eventName:(NSString *)eventName
pageName:(NSString *)eventPageName
extra:(NSDictionary*)extra;
@end
//
// LPEventManager.m
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "RNCusEventManager.h"
#import "RNMonitorConfig.h"
#import "RNUtil.h"
#import "RNDataManager.h"
#import "RNUpdateService.h"
#import "RNDevice.h"
#import "RNCusEventDO.h"
#import "RNMonitorUploadManager.h"
NSString * KReceiveEventNotification = @"KReceiveEventNotification";
@implementation RNCusEventManager
+ (instancetype)shareInstance {
static RNCusEventManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
_eventPath = [RNDataManager creatDataWithFileName:KEventEntityName];
}
- (void)event:(NSString *)eventId
eventName:(NSString *)eventName
pageName:(NSString *)eventPageName
extra:(NSDictionary*)extra {
RNCusEventDO * eventDO = [RNCusEventDO new];
eventDO.epn = eventPageName;
if (eventId) {
eventDO.ei = eventId;
}
if (eventName) {
eventDO.en = eventName;
}
if (extra) {
eventDO.extra = extra;
}
}
@end
//
// RNDeviceManager.h
// RNMonitor
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^RNReadDevices)(BOOL success, NSArray * devices, NSError *error);
@interface RNDeviceManager : NSObject
@property(nonatomic,copy) NSString *devicePath;;
@property(nonatomic,strong) id extra;
+ (instancetype)shareInstance;
- (void)start;
@end
//
// RNDeviceManager.m
// RNMonitor
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNDeviceManager.h"
#import "RNDevice.h"
#import "RNMonitorConfig.h"
#import "RNDataManager.h"
#import "RNUpdateService.h"
#import "RNUtil.h"
#import "RNDeviceDO.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
@interface RNDeviceManager ()
@end
@implementation RNDeviceManager
+ (instancetype)shareInstance {
static RNDeviceManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
[[RNFMDB shareDatabase] jq_createTable:KDeviceEntityName
dicOrModel:[RNDeviceDO new]];
}
return self;
}
- (void)start{
RNDeviceDO *deviceDO = [RNDeviceDO new];
deviceDO.sr = [RNDevice iphoneResolution];
deviceDO.ch = @"appStore";
deviceDO.jb = [NSString stringWithFormat:@"%d",[RNDevice iphoneIsJailbreak]];
deviceDO.rom = [RNDevice diskOfAllSizeMBytes];
deviceDO.mem = [RNDevice availableMemory];
deviceDO.cpu = [RNDevice cpuType];
deviceDO.sdk = [RNDevice minimumSystemVersion];
if (_extra) {
deviceDO.extra = _extra;
}
[RNMonitorUploadManager applyBaseParam:KDeviceEntityName
pageName:nil
data:deviceDO];
}
@end
//
// LPPageManager.h
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * KEventEntityName;
@interface RNEventManager : NSObject
@property(nonatomic,strong) id extra;
+ (instancetype)shareInstance;
- (void)start;
- (void)event:(NSDictionary *)eventParam;
@end
//
// LPPageManager.m
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "RNEventManager.h"
#import "RNMonitorConfig.h"
#import "RNUpdateService.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
#import "RNEventDO.h"
@implementation RNEventManager
+ (instancetype)shareInstance {
static RNEventManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
[[RNFMDB shareDatabase] jq_createTable:KEventEntityName
dicOrModel:[RNEventDO new]];
}
- (void)event:(NSDictionary *)eventParam
{
RNEventDO *eventDO = [RNEventDO new];
[eventDO setValuesForKeysWithDictionary:eventParam];
if (_extra) {
eventDO.extra = _extra;
}
[RNMonitorUploadManager applyBaseParam:KEventEntityName
pageName:nil
data:eventDO];
}
@end
//
// UncaughtExceptionHandler.h
// iOSCrash
//
// Created by wzy on 16/1/15.
// Copyright © 2016年 wzy. All rights reserved.
//
#import <UIKit/UIKit.h>
extern NSString * KReceiveLogNotification;
@interface RNLogManager : NSObject
@property(nonatomic,copy) NSString *logPath;
+ (instancetype)shareInstance;
- (void)start;
- (void)handerReactNativeError:(NSDictionary *)error;
void HandleException(NSException *exception);
void SignalHandler(int signal);
//开启异常检测机制
void InstallUncaughtExceptionHandler(void);
@end
//
// UncaughtExceptionHandler.m
// iOSCrash
//
// Created by wzy on 16/1/15.
// Copyright © 2016年 wzy. All rights reserved.
//
#import "RNLogManager.h"
#include <libkern/OSAtomic.h>
#include <execinfo.h>
#import "RNMonitorConfig.h"
#import "RNDataManager.h"
#import "RNUtil.h"
#import "RNDevice.h"
#import "RNUpdateService.h"
#import "RNLogDO.h"
#import "NSObject+RNMIU_ToDictionary.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
#import "RCTAssert.h"
NSString * KReceiveLogNotification = @"KReceiveLogNotification";
@interface RNLogManager ()<UIAlertViewDelegate>
@end
NSString * const UncaughtExceptionHandlerSignalExceptionName = @"UncaughtExceptionHandlerSignalExceptionName";
NSString * const UncaughtExceptionHandlerSignalKey = @"UncaughtExceptionHandlerSignalKey";
NSString * const UncaughtExceptionHandlerAddressesKey = @"UncaughtExceptionHandlerAddressesKey";
volatile int32_t UncaughtExceptionCount = 0;
const int32_t UncaughtExceptionMaximum = 10;
const NSInteger UncaughtExceptionHandlerSkipAddressCount = 4;
const NSInteger UncaughtExceptionHandlerReportAddressCount = 5;
@implementation RNLogManager{
BOOL dismissed;
}
+ (instancetype)shareInstance {
static RNLogManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
[[RNFMDB shareDatabase] jq_createTable:KLogEntityName dicOrModel: [RNLogDO new]];
InstallUncaughtExceptionHandler();
}
+ (NSArray *)backtrace
{
void* callstack[128];
int frames = backtrace(callstack, 128);
char **strs = backtrace_symbols(callstack, frames);
int i;
NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
for (
i = UncaughtExceptionHandlerSkipAddressCount;
i < UncaughtExceptionHandlerSkipAddressCount +
UncaughtExceptionHandlerReportAddressCount;
i++)
{
[backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);
return backtrace;
}
- (void)validateAndSaveCriticalApplicationData
{
}
- (void)handerReactNativeError:(NSDictionary *)error{
RNLogDO *logDO = [RNLogDO new];
[logDO setValuesForKeysWithDictionary:error];
[RNMonitorUploadManager applyBaseParam:KLogEntityName
pageName:nil
data:logDO];
}
- (void)handleException:(NSException *)exception
{
RNLogDO *logDO = [RNLogDO new];
logDO.erm = [exception reason];
logDO.sta = [[exception userInfo] objectForKey:UncaughtExceptionHandlerAddressesKey] ;
[RNMonitorUploadManager applyBaseParam:KLogEntityName
pageName:nil
data:logDO];
}
@end
// 异常处理
void HandleException(NSException *exception)
{
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum)
{
return;
}
NSArray *callStack = [RNLogManager backtrace];
NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
[[RNLogManager shareInstance] performSelectorOnMainThread:@selector(handleException:)
withObject:[NSException exceptionWithName:[exception name] reason:[exception reason] userInfo:userInfo]
waitUntilDone:YES];
}
void SignalHandler(int signal)
{
int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
if (exceptionCount > UncaughtExceptionMaximum)
{
return;
}
NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey];
NSArray *callStack = [RNLogManager backtrace];
[userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
id exception = [NSException exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
reason:[NSString stringWithFormat:NSLocalizedString(@"Signal %d was raised.", nil),signal]
userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]];
[[RNLogManager shareInstance] performSelectorOnMainThread:@selector(handleException:)
withObject:exception
waitUntilDone:YES];
}
void InstallUncaughtExceptionHandler(void)
{
NSSetUncaughtExceptionHandler(&HandleException);
signal(SIGABRT, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGFPE, SignalHandler);
signal(SIGBUS, SignalHandler);
signal(SIGPIPE, SignalHandler);
}
//
// RNEventDO.h
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import <Foundation/Foundation.h>
#import "RNParamDO.h"
@interface RNCusEventDO : RNParamDO
/** 事件发生的界面*/
@property(nonatomic,copy) NSString *epn;
/** 事件名称*/
@property(nonatomic,copy) NSString *en;
/** 事件id*/
@property(nonatomic,copy) NSString *ei;
@end
//
// RNEventDO.m
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import "RNCusEventDO.h"
@implementation RNCusEventDO
@end
//
// RNDeviceDO.h
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import <Foundation/Foundation.h>
#import "RNParamDO.h"
@interface RNDeviceDO : RNParamDO
/** 渠道 */
@property(nonatomic,copy) NSString *ch;
/** 分辨率 */
@property(nonatomic,copy) NSString *sr;
/** 是否越狱 */
@property(nonatomic,copy) NSString *jb;
/** 磁盘大小 */
@property(nonatomic,copy) NSString *rom;
/** 内存大小 */
@property(nonatomic,copy) NSString *mem;
/** cpu使用 */
@property(nonatomic,copy) NSString *cpu;
/** sdk信息 */
@property(nonatomic,copy) NSString *sdk;
@end
//
// RNDeviceDO.m
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import "RNDeviceDO.h"
@implementation RNDeviceDO
@end
//
// RNEventDO.h
// Pods
//
// Created by zhiyu on 2017/6/29.
//
//
#import "RNParamDO.h"
@interface RNEventDO : RNParamDO
/** 事件坐标x */
@property(nonatomic,copy) NSString *x;
/** 事件坐标y */
@property(nonatomic,copy) NSString *y;
/** xpath */
@property(nonatomic,copy) NSString *xp;
@end
//
// RNEventDO.m
// Pods
//
// Created by zhiyu on 2017/6/29.
//
//
#import "RNEventDO.h"
@implementation RNEventDO
@end
//
// RNLogDO.h
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import <Foundation/Foundation.h>
#import "RNParamDO.h"
@interface RNLogDO : RNParamDO
/** 错误日志*/
@property(nonatomic,copy) NSString *erm;
/** 堆栈信息*/
@property(nonatomic,copy) NSString *sta;
@end
//
// RNLogDO.m
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import "RNLogDO.h"
@implementation RNLogDO
@end
//
// RNPageDO.h
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import <Foundation/Foundation.h>
#import "RNParamDO.h"
@interface RNPageDO : RNParamDO
/** 界面名称 */
@property(nonatomic,copy) NSString *dt;
/** 页面停留时间 */
@property(nonatomic,copy) NSString *tp;
/** 上一个界面的 */
@property(nonatomic,copy) NSString *dr;
@property(nonatomic,copy) NSString* startTime;
@end
//
// RNPageDO.m
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import "RNPageDO.h"
@implementation RNPageDO
@end
//
// RNBaseDO.h
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import <Foundation/Foundation.h>
@interface RNParamDO : NSObject
/** 记录时间 */
@property(nonatomic,copy) NSString *date;
/** 应用id */
@property(nonatomic,copy) NSString *ak;
/** 客户端id(deviceId) */
@property(nonatomic,copy) NSString *cid;
/** 用户id */
@property(nonatomic,copy) NSString *uid;
/** 网络状态 */
@property(nonatomic,copy) NSString *ns;
/** 应用版本 */
@property(nonatomic,copy) NSString *av;
/** 界面名称 */
@property(nonatomic,copy) NSString *dp;
/** appName */
@property(nonatomic,copy) NSString *dh;
/** topic */
@property(nonatomic,copy) NSString *t;
/** gps */
@property(nonatomic,copy) NSString *gps;
/** ip */
@property(nonatomic,copy) NSString *ip;
/** 访问id(deviceId) */
@property(nonatomic,copy) NSString *vid;
/** 设备品牌 */
@property(nonatomic,copy) NSString *br;
/** 设备型号 */
@property(nonatomic,copy) NSString *md;
/** 系统名称 */
@property(nonatomic,copy) NSString *osn;
/** 系统版本 */
@property(nonatomic,copy) NSString *osv;
/** 系统版本 */
@property(nonatomic,copy) NSString *ua;
@property(nonatomic,strong) id extra;
@end
//
// RNBaseDO.m
// Pods
//
// Created by zhiyu on 2017/6/21.
//
//
#import "RNParamDO.h"
@implementation RNParamDO
@end
//
// RNPerformanceDO.h
// Pods
//
// Created by zhiyu on 2017/6/29.
//
//
#import "RNParamDO.h"
@interface RNPerformanceDO : RNParamDO
/** 页面加载时间 */
@property(nonatomic,copy) NSString * nt;
@end
//
// RNPerformanceDO.m
// Pods
//
// Created by zhiyu on 2017/6/29.
//
//
#import "RNPerformanceDO.h"
@implementation RNPerformanceDO
@end
//
// RNRequestDO.h
// Pods
//
// Created by zhiyu on 2017/7/3.
//
//
#import <RNParamDO.h>
@interface RNRequestDO : RNParamDO
/** 请求响应时间 */
@property(nonatomic,copy) NSString * tt;
/** 请求路径 */
@property(nonatomic,copy) NSString * url;
/** 响应状态 */
@property(nonatomic,copy) NSString * st;
/** 请求方法 */
@property(nonatomic,copy) NSString * me;
/** 请求体大小 */
@property(nonatomic,copy) NSString * req;
/** 响应体大小 */
@property(nonatomic,copy) NSString * res;
@end
//
// RNRequestDO.m
// Pods
//
// Created by zhiyu on 2017/7/3.
//
//
#import "RNRequestDO.h"
@implementation RNRequestDO
@end
//
// LPPageManager.h
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * KReceivePageNotification;
typedef void (^RNReadPages)(BOOL success, NSArray * pages, NSError *error);
@interface RNPageManager : NSObject
//@property(nonatomic,copy) NSString *pagePath;
@property(nonatomic,strong) id extra;
+ (instancetype)shareInstance;
- (void)start;
/** 记录某个页面开始的时间.
@param pageName 统计的页面名称.
@param extra 额外参数
*/
- (void)startPageView:(NSString *)pageName lastPage:(NSString*)lastPage;
/** 记录某个页面结束的时间.
@param pageName 统计的页面名称.
*/
- (void)endPageView:(NSString *)pageName;
@end
//
// LPPageManager.m
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "RNPageManager.h"
#import "RNMonitorConfig.h"
#import "RNDataManager.h"
#import "RNDevice.h"
#import "RNUtil.h"
#import "RNUpdateService.h"
#import "RNPageDO.h"
#import "NSObject+RNMIU_ToDictionary.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
NSString * KReceivePageNotification = @"KReceiveDeviceNotification";
@implementation RNPageManager{
NSMutableArray *_currentPageNames;
NSString *_currentPageName;
NSMutableDictionary *_currentData;
}
+ (instancetype)shareInstance {
static RNPageManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
[[RNFMDB shareDatabase] jq_createTable:KPageEntityName dicOrModel:[RNPageDO new]];
_currentData = [NSMutableDictionary dictionary];
}
- (void)startPageView:(NSString *)pageName lastPage:(NSString*)lastPage
{
_currentPageName = pageName;
[_currentPageNames addObject:pageName];
RNPageDO *pageDO = [RNPageDO new];
pageDO.dr = lastPage;
pageDO.startTime = [NSString stringWithFormat:@"%f",CACurrentMediaTime()];
pageDO.dt = pageName;
if (_extra) {
pageDO.extra = _extra;
}
[_currentData setObject:pageDO forKey:pageName];
}
- (void)endPageView:(NSString *)pageName {
if ([_currentData.allKeys containsObject:pageName]) {
RNPageDO *pageDO = _currentData[pageName];
double time =(CACurrentMediaTime() - pageDO.startTime.doubleValue);
pageDO.tp = [NSString stringWithFormat:@"%.0f",time];
[RNMonitorUploadManager applyBaseParam:KPageEntityName
pageName:pageName
data:pageDO];
[_currentData removeObjectForKey:pageName];
_currentPageName = nil;
}
}
@end
//
// RNFPS.h
// RNMonitor
//
// Created by zhiyu on 17/3/7.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RNFPS : NSObject
@property(nonatomic,strong) NSMutableArray* FPSs;
+ (instancetype)shareInstance;
- (void)startFPS;
- (void)stopFPS;
@end
//
// RNFPS.m
// RNMonitor
//
// Created by zhiyu on 17/3/7.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNFPS.h"
@implementation RNFPS{
CADisplayLink *_link;
NSUInteger _count;
NSTimeInterval _lastTime;
}
+ (instancetype)shareInstance {
static RNFPS *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)startFPS {
_link = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
_FPSs = [NSMutableArray array];
}
- (void)tick:(CADisplayLink *)link {
if (_lastTime == 0) {
_lastTime = link.timestamp;
return;
}
_count++;
NSTimeInterval delta = link.timestamp - _lastTime;
if (delta < 1) return;
_lastTime = link.timestamp;
float fps = _count / delta;
_count = 0;
NSLog(@"%f",fps);
[_FPSs addObject:[NSNumber numberWithFloat:fps]];
}
- (void)stopFPS{
[_link invalidate];
_link= nil;
}
- (void)dealloc {
[_link invalidate];
_link= nil;
}
@end
//
// RNNetFlow.h
// RNMonitor
//
// Created by zhiyu on 17/3/17.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNNetFlow : NSObject
+ (NSDictionary *)getNetFlow;
@end
//
// RNNetFlow.m
// RNMonitor
//
// Created by zhiyu on 17/3/17.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNNetFlow.h"
#include <arpa/inet.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
@implementation RNNetFlow
static NSString *const DataCounterKeyWWANSent = @"WWANSent";
static NSString *const DataCounterKeyWWANReceived = @"WWANReceived";
static NSString *const DataCounterKeyWiFiSent = @"WiFiSent";
static NSString *const DataCounterKeyWiFiReceived = @"WiFiReceived";
+ (NSDictionary *)getNetFlow
{
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
u_int32_t WiFiSent = 0;
u_int32_t WiFiReceived = 0;
u_int32_t WWANSent = 0;
u_int32_t WWANReceived = 0;
if (getifaddrs(&addrs) == 0)
{
cursor = addrs;
while (cursor != NULL)
{
if (cursor->ifa_addr->sa_family == AF_LINK)
{
#ifdef DEBUG
const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
if(ifa_data != NULL)
{
NSLog(@"Interface name %s: sent %tu received %tu",cursor->ifa_name,ifa_data->ifi_obytes,ifa_data->ifi_ibytes);
}
#endif
// name of interfaces:
// en0 is WiFi
// pdp_ip0 is WWAN
NSString *name = [NSString stringWithFormat:@"%s",cursor->ifa_name];
if ([name hasPrefix:@"en"])
{
const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
if(ifa_data != NULL)
{
WiFiSent += ifa_data->ifi_obytes;
WiFiReceived += ifa_data->ifi_ibytes;
}
}
if ([name hasPrefix:@"pdp_ip"])
{
const struct if_data *ifa_data = (struct if_data *)cursor->ifa_data;
if(ifa_data != NULL)
{
WWANSent += ifa_data->ifi_obytes;
WWANReceived += ifa_data->ifi_ibytes;
}
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
NSLog(@"nwifiSend:%.2f MBnwifiReceived:%.2f MBn wwansend:%.2f MBn wwanreceived:%.2f MBn",WiFiSent/1024.0/1024.0,WiFiReceived/1024.0/1024.0,WWANSent/1024.0/1024.0,WWANReceived/1024.0/1024.0);
return @{DataCounterKeyWiFiSent:[NSNumber numberWithUnsignedInt:WiFiSent],
DataCounterKeyWiFiReceived:[NSNumber numberWithUnsignedInt:WiFiReceived],
DataCounterKeyWWANSent:[NSNumber numberWithUnsignedInt:WWANSent],
DataCounterKeyWWANReceived:[NSNumber numberWithUnsignedInt:WWANReceived]};
}
@end
//
// RNNetWorkFlow.h
// RNMonitor
//
// Created by zhiyu on 17/3/8.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNNetWorkFlow : NSObject
@property (nonatomic, assign) u_int32_t kWiFiSent;
@property (nonatomic, assign) u_int32_t kWiFiReceived;
@property (nonatomic, assign) u_int32_t kWWANSent;
@property (nonatomic, assign) u_int32_t kWWANReceived;
+ (instancetype)shareInstance;
- (uint32_t)currentNetFlow;
- (void)startblock:(void (^)(u_int32_t sendFlow, u_int32_t receivedFlow))block;
- (void)stop;
@end
//
// RNNetWorkFlow.m
// RNMonitor
//
// Created by zhiyu on 17/3/8.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNNetWorkFlow.h"
#include <ifaddrs.h>
#include <net/if.h>
@interface RNNetWorkFlow()
@property (nonatomic, copy) void (^netBlock)(u_int32_t sendFlow, u_int32_t receivedFlow); //每秒获取
@property (assign,nonatomic) uint32_t historySent;
@property (assign,nonatomic) uint32_t historyRecived;
@property (assign,nonatomic) BOOL isFirst;
@property (nonatomic, strong)NSTimer *timer;
@end
@implementation RNNetWorkFlow
+ (instancetype)shareInstance {
static RNNetWorkFlow *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (instancetype)init {
if ([super init]) {
[self getNetflow];
}
return self;
}
- (void)dealloc {
[self.timer invalidate];
self.timer = nil;
self.netBlock = nil;
}
- (void)startblock:(void (^)(u_int32_t sendFlow, u_int32_t receivedFlow))block {
self.netBlock = block;
self.isFirst = YES;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(getNetflow) userInfo:nil repeats:YES];
}
- (void)stop {
[self.timer invalidate];
self.timer = nil;
}
- (uint32_t)currentNetFlow{
return self.historySent + self.historyRecived;
}
/** 流量消耗状态 **/
- (void)getNetflow {
BOOL success;
struct ifaddrs *addrs;
const struct ifaddrs *cursor;
const struct if_data *networkStatisc;
self.kWiFiSent = 0;
self.kWiFiReceived = 0;
self.kWWANSent = 0;
self.kWWANReceived = 0;
NSString *name = @"";
success = getifaddrs(&addrs) == 0;
if (success)
{
cursor = addrs;
while (cursor != NULL)
{
name=[NSString stringWithFormat:@"%s",cursor->ifa_name];
// names of interfaces: en0 is WiFi ,pdp_ip0 is WWAN
if (cursor->ifa_addr->sa_family == AF_LINK)
{
if ([name hasPrefix:@"en"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
self.kWiFiSent+=networkStatisc->ifi_obytes;
self.kWiFiReceived+=networkStatisc->ifi_ibytes;
}
if ([name hasPrefix:@"pdp_ip"])
{
networkStatisc = (const struct if_data *) cursor->ifa_data;
self.kWWANSent+=networkStatisc->ifi_obytes;
self.kWWANReceived+=networkStatisc->ifi_ibytes;
}
}
cursor = cursor->ifa_next;
}
freeifaddrs(addrs);
}
//第一次不统计
if (self.isFirst) {
self.isFirst = NO;
}
else {
uint32_t nowSent = (self.kWiFiSent + self.kWWANSent - self.historySent);
uint32_t nowRecived = (self.kWiFiReceived + self.kWWANReceived - self.historyRecived);
if (self.netBlock) {
self.netBlock(nowSent, nowRecived);
}
}
self.historySent = self.kWiFiSent + self.kWWANSent;
self.historyRecived = self.kWiFiReceived + self.kWWANReceived;
}
@end
//
// RNFlow.h
// RNMonitor
//
// Created by zhiyu on 17/3/9.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNNetworkFlowProtocol : NSURLProtocol
@property(nonatomic,assign)NSUInteger currentFlow;
@end
//
// RNFlow.m
// RNMonitor
//
// Created by zhiyu on 17/3/9.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNNetworkFlowProtocol.h"
#import "RNPerformanceManager.h"
static NSString * const kLPNetworkProtocolHeaderKey = @"networkProtocol";
@interface RNNetworkFlowProtocol ()<NSURLConnectionDataDelegate>
@property(nonatomic,weak)NSURLConnection *connection;
@end
@implementation RNNetworkFlowProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if ([NSURLProtocol propertyForKey:kLPNetworkProtocolHeaderKey inRequest:request] ) {
return NO;
}
if([@[@"http",@"https"] containsObject:request.URL.scheme]){
return YES;
}
return NO;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)startLoading {
NSMutableURLRequest *newRequest = [self.request mutableCopy];
newRequest.allHTTPHeaderFields = self.request.allHTTPHeaderFields;
[NSURLProtocol setProperty:@YES forKey:kLPNetworkProtocolHeaderKey inRequest:self.request];
self.connection = [NSURLConnection connectionWithRequest:self.request delegate:self];
[self.connection start];
}
- (void)stopLoading {
[self.client URLProtocolDidFinishLoading:self];
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(connection.originalRequest){
// [[RNPerformanceManager shareInstance] updateNetworkFlow:connection.originalRequest.HTTPBody.length];
}
[self.client URLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.client URLProtocol:self didLoadData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self.client URLProtocol:self didFailWithError:error];
}
@end
//
// LPPerformancemanager.h
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RNPerformanceManager : NSObject
@property(nonatomic,copy) NSString *performancePath;
+ (instancetype)shareInstance;
- (void)start;
//- (void)updateNetworkFlow:(NSUInteger)flow;
/** 记录某个页面的加载时间.
@param pageName 统计的页面名称.
@param time 页面加载时长
@param extra 额外参数
*/
- (void)pageLoadTime:(NSString*)pageName time:(NSString*)time;
//
//- (void)startPagePerformance:(NSString*)pageName;
//- (void)endPagePerformance:(NSDictionary*)extra;
@end
//
// LPPerformancemanager.m
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "RNPerformanceManager.h"
#import "RNDataManager.h"
#import <RNDevice.h>
#import "RNFPS.h"
#import "RNSlack.h"
#import "RNMonitorConfig.h"
#import "RNUtil.h"
#import "RNNetFlow.h"
#import "RNNetworkFlowProtocol.h"
#import "RNPerformanceDO.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
@implementation RNPerformanceManager{
NSString *_currentPageName;
NSUInteger *_currentFlow;
}
+ (instancetype)shareInstance {
static RNPerformanceManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
[[RNFMDB shareDatabase] jq_createTable:KPerformanceEntityName
dicOrModel:[RNPerformanceDO new]];
// [[RNSlack sharedInstance] startMonitor];
// [self startNetWorkFlowProtocol];
}
- (void)pageLoadTime:(NSString *)pageName time:(NSString *)time
{
RNPerformanceDO* perDO = [RNPerformanceDO new];
perDO.nt = time;
[RNMonitorUploadManager applyBaseParam:KPerformanceEntityName
pageName:pageName
data:perDO];
}
//- (void)startNetWorkFlowProtocol{
// Class networkFlowProtocol = NSClassFromString(@"RNNetworkFlowProtocol");
// [NSURLProtocol registerClass:networkFlowProtocol];
//}
//-(void)updateNetworkFlow:(NSUInteger)flow
//{
// _currentFlow += flow;
//}
//- (void)startPagePerformance:(NSString *)pageName
//{
// [[RNFPS shareInstance] startFPS];
// _currentPageName = pageName;
//}
//
//- (void)endPagePerformance:(NSDictionary *)extra
//{
//// NSDictionary *flew = [RNNetFlow getNetFlow];
// if (_currentPageName) {
// [[RNFPS shareInstance] stopFPS];
// NSNumber *FPS = [[RNFPS shareInstance].FPSs valueForKeyPath:@"@avg.floatValue"];
// unsigned int netWorkFlow = [RNNetFlow getNetFlow];
// NSMutableDictionary *dict = [NSMutableDictionary dictionary];
// [dict setObject:_currentPageName forKey:@"PageName"];
// [dict setObject:[NSString stringWithFormat:@"%f",[RNDevice iphoneCpuUsage]]forKey:@"cpu"];
// [dict setObject:[NSString stringWithFormat:@"%f",[RNDevice iphoneUsedMemory]]forKey:@"mem"];
// [dict setObject:[NSString stringWithFormat:@"%f",FPS.floatValue]forKey:@"fps"];
// [dict setObject:[NSString stringWithFormat:@"%ld",_currentFlow] forKey:@"netflow"];
// [dict setObject:[RNUtil getCurrentTime] forKey:@"date"];
// _currentPageName = nil;
//
// if ([RNMonitorConfig shareInstance].uid) {
// [dict setObject:[RNMonitorConfig shareInstance].uid forKey:@"uid"];
// }
//
// }
//
//}
@end
//
// RNSlack.h
// RNMonitor
//
// Created by zhiyu on 17/3/7.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNSlack : NSObject
@property(nonatomic,strong) NSMutableArray *backSlack;
+ (instancetype) sharedInstance;
- (void) startMonitor;
- (void) endMonitor;
@end
//
// RNSlack.m
// RNMonitor
//
// Created by zhiyu on 17/3/7.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNSlack.h"
#import <libkern/OSAtomic.h>
#import <execinfo.h>
@interface RNSlack(){
CFRunLoopObserverRef _observer;
dispatch_semaphore_t _semaphore;
CFRunLoopActivity _activity;
NSInteger _countTime;
}
@end
@implementation RNSlack
+ (instancetype) sharedInstance{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (void) startMonitor{
// [self registerObserver];
}
- (void) endMonitor{
if (!_observer) {
return;
}
CFRunLoopRemoveObserver(CFRunLoopGetMain(), _observer, kCFRunLoopCommonModes);
CFRelease(_observer);
_observer = NULL;
}
static void runLoopObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
RNSlack *instrance = [RNSlack sharedInstance];
instrance->_activity = activity;
// 发送信号
dispatch_semaphore_t semaphore = instrance->_semaphore;
dispatch_semaphore_signal(semaphore);
}
- (void)registerObserver
{
CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
_observer = CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopAllActivities,
YES,
0,
&runLoopObserverCallBack,
&context);
CFRunLoopAddObserver(CFRunLoopGetMain(), _observer, kCFRunLoopCommonModes);
// 创建信号
_semaphore = dispatch_semaphore_create(0);
// 在子线程监控时长
dispatch_async(dispatch_get_global_queue(0, 0), ^{
while (YES)
{
// 假定连续5次超时50ms认为卡顿(当然也包含了单次超时250ms)
long st = dispatch_semaphore_wait(_semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC));
if (st != 0)
{
if (_activity==kCFRunLoopBeforeSources || _activity==kCFRunLoopAfterWaiting)
{
if (++_countTime < 5)
continue;
[self logStack];
}
}
_countTime = 0;
}
});
}
- (void)logStack{
void* callstack[128];
int frames = backtrace(callstack, 128);
char **strs = backtrace_symbols(callstack, frames);
int i;
_backSlack = [NSMutableArray arrayWithCapacity:frames];
for ( i = 0 ; i < frames ; i++ ){
[_backSlack addObject:[NSString stringWithUTF8String:strs[i]]];
}
free(strs);
}
@end
//
// LPPageManager.h
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSString * KRequestEntityName;
@interface RNRequestManager : NSObject
@property(nonatomic,strong) id extra;
+ (instancetype)shareInstance;
- (void)start;
- (void)sendRequest:(NSDictionary*)requestParam;
@end
//
// LPPageManager.m
// demo
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "RNRequestManager.h"
#import "RNMonitorConfig.h"
#import "RNUpdateService.h"
#import "RNRequestDO.h"
#import "RNFMDB.h"
#import "RNMonitorUploadManager.h"
@implementation RNRequestManager
+ (instancetype)shareInstance {
static RNRequestManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (void)start{
[[RNFMDB shareDatabase] jq_createTable:KRequestEntityName
dicOrModel:[RNRequestDO new]];
// Class networkFlowProtocol = NSClassFromString(@"RNNetworkFlowProtocol");
// [NSURLProtocol registerClass:networkFlowProtocol];
}
- (void)sendRequest:(NSDictionary *)requestParam
{
RNRequestDO *requestDO = [RNRequestDO new];
[requestDO setValuesForKeysWithDictionary:requestParam];
if (_extra) {
requestDO.extra = _extra;
}
[RNMonitorUploadManager applyBaseParam:KRequestEntityName
pageName:nil
data:requestDO];
}
@end
//
// JQFMDB.h
//
// Created by Joker on 17/3/7.
// GitHub: https://github.com/gaojunquan/JQFMDB
//
#import <Foundation/Foundation.h>
@interface RNFMDB : NSObject
/**
(主键id,自动创建) 返回最后插入的primary key id
@param tableName 表的名称
*/
- (NSInteger)lastInsertPrimaryKeyId:(NSString *)tableName;
/**
单例方法创建数据库, 如果使用shareDatabase创建,则默认在NSDocumentDirectory下创建JQFMDB.sqlite, 但只要使用这三个方法任意一个创建成功, 之后即可使用三个中任意一个方法获得同一个实例,参数可随意或nil
dbName 数据库的名称 如: @"Users.sqlite", 如果dbName = nil,则默认dbName=@"JQFMDB.sqlite"
dbPath 数据库的路径, 如果dbPath = nil, 则路径默认为NSDocumentDirectory
*/
+ (instancetype)shareDatabase;
+ (instancetype)shareDatabase:(NSString *)dbName;
+ (instancetype)shareDatabase:(NSString *)dbName path:(NSString *)dbPath;
/**
非单例方法创建数据库
@param dbName 数据库的名称 如: @"Users.sqlite"
dbPath 数据库的路径, 如果dbPath = nil, 则路径默认为NSDocumentDirectory
*/
- (instancetype)initWithDBName:(NSString *)dbName;
- (instancetype)initWithDBName:(NSString *)dbName path:(NSString *)dbPath;
/**
创建表 通过传入的model或dictionary(如果是字典注意类型要写对),虽然都可以不过还是推荐以下都用model
@param tableName 表的名称
@param parameters 设置表的字段,可以传model(runtime自动生成字段)或字典(格式:@{@"name":@"TEXT"})
@return 是否创建成功
*/
- (BOOL)jq_createTable:(NSString *)tableName dicOrModel:(id)parameters;
/**
同上,
@param nameArr 不允许model或dic里的属性/key生成表的字段,如:nameArr = @[@"name"],则不允许名为name的属性/key 生成表的字段
*/
- (BOOL)jq_createTable:(NSString *)tableName dicOrModel:(id)parameters excludeName:(NSArray *)nameArr;
/**
增加: 向表中插入数据
@param tableName 表的名称
@param parameters 要插入的数据,可以是model或dictionary(格式:@{@"name":@"小李"})
@return 是否插入成功
*/
- (BOOL)jq_insertTable:(NSString *)tableName dicOrModel:(id)parameters;
/**
删除: 根据条件删除表中数据
@param tableName 表的名称
@param format 条件语句, 如:@"where name = '小李'"
@return 是否删除成功
*/
- (BOOL)jq_deleteTable:(NSString *)tableName whereFormat:(NSString *)format, ...;
/**
更改: 根据条件更改表中数据
@param tableName 表的名称
@param parameters 要更改的数据,可以是model或dictionary(格式:@{@"name":@"张三"})
@param format 条件语句, 如:@"where name = '小李'"
@return 是否更改成功
*/
- (BOOL)jq_updateTable:(NSString *)tableName dicOrModel:(id)parameters whereFormat:(NSString *)format, ...;
/**
查找: 根据条件查找表中数据
@param tableName 表的名称
@param parameters 每条查找结果放入model(可以是[Person class] or @"Person" or Person实例)或dictionary中
@param format 条件语句, 如:@"where name = '小李'",
@return 将结果存入array,数组中的元素的类型为parameters的类型
*/
- (NSArray *)jq_lookupTable:(NSString *)tableName dicOrModel:(id)parameters whereFormat:(NSString *)format, ...;
/**
批量插入或更改
@param dicOrModelArray 要insert/update数据的数组,也可以将model和dictionary混合装入array
@return 返回的数组存储未插入成功的下标,数组中元素类型为NSNumber
*/
- (NSArray *)jq_insertTable:(NSString *)tableName dicOrModelArray:(NSArray *)dicOrModelArray;
// `删除表
- (BOOL)jq_deleteTable:(NSString *)tableName;
// `清空表
- (BOOL)jq_deleteAllDataFromTable:(NSString *)tableName;
// `是否存在表
- (BOOL)jq_isExistTable:(NSString *)tableName;
// `表中共有多少条数据
- (int)jq_tableItemCount:(NSString *)tableName;
// `返回表中的字段名
- (NSArray *)jq_columnNameArray:(NSString *)tableName;
// `关闭数据库
- (void)close;
// `打开数据库 (每次shareDatabase系列操作时已经open,当调用close后若进行db操作需重新open或调用shareDatabase)
- (void)open;
/**
增加新字段, 在建表后还想新增字段,可以在原建表model或新model中新增对应属性,然后传入即可新增该字段,该操作已在事务中执行
@param tableName 表的名称
@param parameters 如果传Model:数据库新增字段为建表时model所没有的属性,如果传dictionary格式为@{@"newname":@"TEXT"}
@param nameArr 不允许生成字段的属性名的数组
@return 是否成功
*/
- (BOOL)jq_alterTable:(NSString *)tableName dicOrModel:(id)parameters excludeName:(NSArray *)nameArr;
- (BOOL)jq_alterTable:(NSString *)tableName dicOrModel:(id)parameters;
// ============================= 线程安全操作 ===============================
/**
将操作语句放入block中即可保证线程安全, 如:
Person *p = [[Person alloc] init];
p.name = @"小李";
[jqdb jq_inDatabase:^{
[jqdb jq_insertTable:@"users" dicOrModel:p];
}];
*/
- (void)jq_inDatabase:(void (^)(void))block;
/**
事务: 将操作语句放入block中可执行回滚操作(*rollback = YES;)
Person *p = [[Person alloc] init];
p.name = @"小李";
for (int i=0,i < 1000,i++) {
[jq jq_inTransaction:^(BOOL *rollback) {
BOOL flag = [jq jq_insertTable:@"users" dicOrModel:p];
if (!flag) {
*rollback = YES; //只要有一次不成功,则进行回滚操作
return;
}
}];
}
*/
- (void)jq_inTransaction:(void(^)(BOOL *rollback))block;
@end
//
// JQFMDB.m
//
// Created by Joker on 17/3/7.
// GitHub: https://github.com/gaojunquan/JQFMDB
//
#import "RNFMDB.h"
#import "FMDB.h"
#import <objc/runtime.h>
// 数据库中常见的几种类型
#define SQL_TEXT @"TEXT" //文本
#define SQL_INTEGER @"INTEGER" //int long integer ...
#define SQL_REAL @"REAL" //浮点
#define SQL_BLOB @"BLOB" //data
@interface RNFMDB ()
@property (nonatomic, strong)NSString *dbPath;
@property (nonatomic, strong)FMDatabaseQueue *dbQueue;
@property (nonatomic, strong)FMDatabase *db;
@end
@implementation RNFMDB
- (FMDatabaseQueue *)dbQueue
{
if (!_dbQueue) {
FMDatabaseQueue *fmdb = [FMDatabaseQueue databaseQueueWithPath:_dbPath];
self.dbQueue = fmdb;
[_db close];
self.db = [fmdb valueForKey:@"_db"];
}
return _dbQueue;
}
static RNFMDB *jqdb = nil;
+ (instancetype)shareDatabase
{
return [RNFMDB shareDatabase:nil];
}
+ (instancetype)shareDatabase:(NSString *)dbName
{
return [RNFMDB shareDatabase:dbName path:nil];
}
+ (instancetype)shareDatabase:(NSString *)dbName path:(NSString *)dbPath
{
if (!jqdb) {
NSString *path;
if (!dbName) {
dbName = @"JQFMDB.sqlite";
}
if (!dbPath) {
path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:dbName];
} else {
path = [dbPath stringByAppendingPathComponent:dbName];
}
FMDatabase *fmdb = [FMDatabase databaseWithPath:path];
if ([fmdb open]) {
jqdb = RNFMDB.new;
jqdb.db = fmdb;
jqdb.dbPath = path;
}
}
if (![jqdb.db open]) {
NSLog(@"database can not open !");
return nil;
};
return jqdb;
}
- (instancetype)initWithDBName:(NSString *)dbName
{
return [self initWithDBName:dbName path:nil];
}
- (instancetype)initWithDBName:(NSString *)dbName path:(NSString *)dbPath
{
if (!dbName) {
dbName = @"JQFMDB.sqlite";
}
NSString *path;
if (!dbPath) {
path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:dbName];
} else {
path = [dbPath stringByAppendingPathComponent:dbName];
}
FMDatabase *fmdb = [FMDatabase databaseWithPath:path];
if ([fmdb open]) {
self = [self init];
if (self) {
self.db = fmdb;
self.dbPath = path;
return self;
}
}
return nil;
}
- (BOOL)jq_createTable:(NSString *)tableName dicOrModel:(id)parameters
{
return [self jq_createTable:tableName dicOrModel:parameters excludeName:nil];
}
- (BOOL)jq_createTable:(NSString *)tableName dicOrModel:(id)parameters excludeName:(NSArray *)nameArr
{
NSDictionary *dic;
if ([parameters isKindOfClass:[NSDictionary class]]) {
dic = parameters;
} else {
Class CLS;
if ([parameters isKindOfClass:[NSString class]]) {
if (!NSClassFromString(parameters)) {
CLS = nil;
} else {
CLS = NSClassFromString(parameters);
}
}else if ([parameters isKindOfClass:[NSObject class]]) {
NSMutableDictionary*dict = [NSMutableDictionary dictionary];
NSString * currentCLS =[NSString stringWithUTF8String:class_getName([parameters class])];
NSString * NSObjectString = [NSString stringWithUTF8String:class_getName([NSObject class])];
while (![currentCLS isEqualToString:NSObjectString] ) {
Class cuCLS = NSClassFromString(currentCLS);
[dict addEntriesFromDictionary:[self modelToDictionary:cuCLS excludePropertyName:nameArr]];
currentCLS =[NSString stringWithUTF8String:class_getName(class_getSuperclass(cuCLS))];
}
dic = dict;
} else {
CLS = parameters;
dic = [self modelToDictionary:CLS excludePropertyName:nameArr];
}
}
NSMutableString *fieldStr = [[NSMutableString alloc] initWithFormat:@"CREATE TABLE %@ (pkid INTEGER PRIMARY KEY,", tableName];
int keyCount = 0;
for (NSString *key in dic) {
keyCount++;
if ((nameArr && [nameArr containsObject:key]) || [key isEqualToString:@"pkid"]) {
continue;
}
if (keyCount == dic.count) {
[fieldStr appendFormat:@" %@ %@)", key, dic[key]];
break;
}
[fieldStr appendFormat:@" %@ %@,", key, dic[key]];
}
BOOL creatFlag;
creatFlag = [_db executeUpdate:fieldStr];
return creatFlag;
}
- (NSString *)createTable:(NSString *)tableName dictionary:(NSDictionary *)dic excludeName:(NSArray *)nameArr
{
NSMutableString *fieldStr = [[NSMutableString alloc] initWithFormat:@"CREATE TABLE %@ (pkid INTEGER PRIMARY KEY,", tableName];
int keyCount = 0;
for (NSString *key in dic) {
keyCount++;
if ((nameArr && [nameArr containsObject:key]) || [key isEqualToString:@"pkid"]) {
continue;
}
if (keyCount == dic.count) {
[fieldStr appendFormat:@" %@ %@)", key, dic[key]];
break;
}
[fieldStr appendFormat:@" %@ %@,", key, dic[key]];
}
return fieldStr;
}
- (NSString *)createTable:(NSString *)tableName model:(Class)cls excludeName:(NSArray *)nameArr
{
NSMutableString *fieldStr = [[NSMutableString alloc] initWithFormat:@"CREATE TABLE %@ (pkid INTEGER PRIMARY KEY,", tableName];
NSDictionary *dic = [self modelToDictionary:cls excludePropertyName:nameArr];
int keyCount = 0;
for (NSString *key in dic) {
keyCount++;
if ([key isEqualToString:@"pkid"]) {
continue;
}
if (keyCount == dic.count) {
[fieldStr appendFormat:@" %@ %@)", key, dic[key]];
break;
}
[fieldStr appendFormat:@" %@ %@,", key, dic[key]];
}
return fieldStr;
}
#pragma mark - *************** runtime
- (NSDictionary *)modelToDictionary:(Class)cls excludePropertyName:(NSArray *)nameArr
{
NSMutableDictionary *mDic = [NSMutableDictionary dictionaryWithCapacity:0];
unsigned int outCount;
objc_property_t *properties = class_copyPropertyList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
NSString *name = [NSString stringWithCString:property_getName(properties[i]) encoding:NSUTF8StringEncoding];
if ([nameArr containsObject:name]) continue;
NSString *type = [NSString stringWithCString:property_getAttributes(properties[i]) encoding:NSUTF8StringEncoding];
id value = [self propertTypeConvert:type];
if (value) {
[mDic setObject:value forKey:name];
}
}
free(properties);
return mDic;
}
// 获取model的key和value
- (NSDictionary *)getModelPropertyKeyValue:(id)model tableName:(NSString *)tableName clomnArr:(NSArray *)clomnArr
{
NSMutableDictionary*dict = [NSMutableDictionary dictionary];
if ([model isKindOfClass:[NSObject class]]) {
NSString * currentCLS =[NSString stringWithUTF8String:class_getName([model class])];
NSString * NSObjectString = [NSString stringWithUTF8String:class_getName([NSObject class])];
while (![currentCLS isEqualToString:NSObjectString] ) {
Class cuCLS = NSClassFromString(currentCLS);
[dict addEntriesFromDictionary:[[RNFMDB shareDatabase] modelToDictionary:cuCLS excludePropertyName:nil]];
currentCLS =[NSString stringWithUTF8String:class_getName(class_getSuperclass(cuCLS))];
}
}
NSMutableDictionary *mDic = [NSMutableDictionary dictionaryWithCapacity:0];
NSArray *properties = dict.allKeys;
for (int i = 0; i < properties.count; i++) {
NSString *name = properties[i];
if (![clomnArr containsObject:name]) {
continue;
}
id value = [model valueForKey:name];
if (value) {
[mDic setObject:value forKey:name];
}
}
return mDic;
}
- (NSString *)propertTypeConvert:(NSString *)typeStr
{
NSString *resultStr = nil;
if ([typeStr hasPrefix:@"T@\"NSString\""]) {
resultStr = SQL_TEXT;
} else if ([typeStr hasPrefix:@"T@\"NSData\""]) {
resultStr = SQL_BLOB;
} else if ([typeStr hasPrefix:@"Ti"]||[typeStr hasPrefix:@"TI"]||[typeStr hasPrefix:@"Ts"]||[typeStr hasPrefix:@"TS"]||[typeStr hasPrefix:@"T@\"NSNumber\""]||[typeStr hasPrefix:@"TB"]||[typeStr hasPrefix:@"Tq"]||[typeStr hasPrefix:@"TQ"]) {
resultStr = SQL_INTEGER;
} else if ([typeStr hasPrefix:@"Tf"] || [typeStr hasPrefix:@"Td"]){
resultStr= SQL_REAL;
}
return resultStr;
}
// 得到表里的字段名称
- (NSArray *)getColumnArr:(NSString *)tableName db:(FMDatabase *)db
{
NSMutableArray *mArr = [NSMutableArray arrayWithCapacity:0];
FMResultSet *resultSet = [db getTableSchema:tableName];
while ([resultSet next]) {
[mArr addObject:[resultSet stringForColumn:@"name"]];
}
return mArr;
}
#pragma mark - *************** 增删改查
- (BOOL)jq_insertTable:(NSString *)tableName dicOrModel:(id)parameters
{
NSArray *columnArr = [self getColumnArr:tableName db:_db];
return [self insertTable:tableName dicOrModel:parameters columnArr:columnArr];
}
- (BOOL)insertTable:(NSString *)tableName dicOrModel:(id)parameters columnArr:(NSArray *)columnArr
{
BOOL flag;
NSDictionary *dic;
if ([parameters isKindOfClass:[NSDictionary class]]) {
dic = parameters;
}else {
dic = [self getModelPropertyKeyValue:parameters tableName:tableName clomnArr:columnArr];
}
NSMutableString *finalStr = [[NSMutableString alloc] initWithFormat:@"INSERT INTO %@ (", tableName];
NSMutableString *tempStr = [NSMutableString stringWithCapacity:0];
NSMutableArray *argumentsArr = [NSMutableArray arrayWithCapacity:0];
for (NSString *key in dic) {
if (![columnArr containsObject:key] || [key isEqualToString:@"pkid"]) {
continue;
}
[finalStr appendFormat:@"%@,", key];
[tempStr appendString:@"?,"];
[argumentsArr addObject:dic[key]];
}
[finalStr deleteCharactersInRange:NSMakeRange(finalStr.length-1, 1)];
if (tempStr.length)
[tempStr deleteCharactersInRange:NSMakeRange(tempStr.length-1, 1)];
[finalStr appendFormat:@") values (%@)", tempStr];
flag = [_db executeUpdate:finalStr withArgumentsInArray:argumentsArr];
return flag;
}
- (BOOL)jq_deleteTable:(NSString *)tableName whereFormat:(NSString *)format, ...
{
va_list args;
va_start(args, format);
NSString *where = format?[[NSString alloc] initWithFormat:format locale:[NSLocale currentLocale] arguments:args]:format;
va_end(args);
BOOL flag;
NSMutableString *finalStr = [[NSMutableString alloc] initWithFormat:@"delete from %@ %@", tableName,where];
flag = [_db executeUpdate:finalStr];
return flag;
}
- (BOOL)jq_updateTable:(NSString *)tableName dicOrModel:(id)parameters whereFormat:(NSString *)format, ...
{
va_list args;
va_start(args, format);
NSString *where = format?[[NSString alloc] initWithFormat:format locale:[NSLocale currentLocale] arguments:args]:format;
va_end(args);
BOOL flag;
NSDictionary *dic;
NSArray *clomnArr = [self getColumnArr:tableName db:_db];
if ([parameters isKindOfClass:[NSDictionary class]]) {
dic = parameters;
}else {
dic = [self getModelPropertyKeyValue:parameters tableName:tableName clomnArr:clomnArr];
}
NSMutableString *finalStr = [[NSMutableString alloc] initWithFormat:@"update %@ set ", tableName];
NSMutableArray *argumentsArr = [NSMutableArray arrayWithCapacity:0];
for (NSString *key in dic) {
if (![clomnArr containsObject:key] || [key isEqualToString:@"pkid"]) {
continue;
}
[finalStr appendFormat:@"%@ = %@,", key, @"?"];
[argumentsArr addObject:dic[key]];
}
[finalStr deleteCharactersInRange:NSMakeRange(finalStr.length-1, 1)];
if (where.length) [finalStr appendFormat:@" %@", where];
flag = [_db executeUpdate:finalStr withArgumentsInArray:argumentsArr];
return flag;
}
- (NSArray *)jq_lookupTable:(NSString *)tableName dicOrModel:(id)parameters whereFormat:(NSString *)format, ...
{
va_list args;
va_start(args, format);
NSString *where = format?[[NSString alloc] initWithFormat:format locale:[NSLocale currentLocale] arguments:args]:format;
va_end(args);
NSMutableArray *resultMArr = [NSMutableArray arrayWithCapacity:0];
NSDictionary *dic;
NSMutableString *finalStr = [[NSMutableString alloc] initWithFormat:@"select * from %@ %@", tableName, where?where:@""];
NSArray *clomnArr = [self getColumnArr:tableName db:_db];
FMResultSet *set = [_db executeQuery:finalStr];
if ([[parameters class] isSubclassOfClass:[NSDictionary class]]) {
dic = parameters;
while ([set next]) {
NSMutableDictionary *resultDic = [NSMutableDictionary dictionaryWithCapacity:0];
for (NSString *key in clomnArr) {
id value = [set objectForColumnName:key];
if(value){
[resultDic setObject:value forKey:key];
}
}
if (resultDic) [resultMArr addObject:resultDic];
}
}else {
Class CLS;
if ([parameters isKindOfClass:[NSString class]]) {
if (!NSClassFromString(parameters)) {
CLS = nil;
} else {
CLS = NSClassFromString(parameters);
}
} else if ([parameters isKindOfClass:[NSObject class]]) {
CLS = [parameters class];
} else {
CLS = parameters;
}
if (CLS) {
NSDictionary *propertyType = [self modelToDictionary:CLS excludePropertyName:nil];
while ([set next]) {
id model = CLS.new;
for (NSString *name in clomnArr) {
if ([propertyType[name] isEqualToString:SQL_TEXT]) {
id value = [set stringForColumn:name];
if (value)
[model setValue:value forKey:name];
} else if ([propertyType[name] isEqualToString:SQL_INTEGER]) {
[model setValue:@([set longLongIntForColumn:name]) forKey:name];
} else if ([propertyType[name] isEqualToString:SQL_REAL]) {
[model setValue:[NSNumber numberWithDouble:[set doubleForColumn:name]] forKey:name];
} else if ([propertyType[name] isEqualToString:SQL_BLOB]) {
id value = [set dataForColumn:name];
if (value)
[model setValue:value forKey:name];
}
}
[resultMArr addObject:model];
}
}
}
return resultMArr;
}
// 直接传一个array插入
- (NSArray *)jq_insertTable:(NSString *)tableName dicOrModelArray:(NSArray *)dicOrModelArray
{
int errorIndex = 0;
NSMutableArray *resultMArr = [NSMutableArray arrayWithCapacity:0];
NSArray *columnArr = [self getColumnArr:tableName db:_db];
for (id parameters in dicOrModelArray) {
BOOL flag = [self insertTable:tableName dicOrModel:parameters columnArr:columnArr];
if (!flag) {
[resultMArr addObject:@(errorIndex)];
}
errorIndex++;
}
return resultMArr;
}
- (BOOL)jq_deleteTable:(NSString *)tableName
{
NSString *sqlstr = [NSString stringWithFormat:@"DROP TABLE %@", tableName];
if (![_db executeUpdate:sqlstr])
{
return NO;
}
return YES;
}
- (BOOL)jq_deleteAllDataFromTable:(NSString *)tableName
{
NSString *sqlstr = [NSString stringWithFormat:@"DELETE FROM %@", tableName];
if (![_db executeUpdate:sqlstr])
{
return NO;
}
return YES;
}
- (BOOL)jq_isExistTable:(NSString *)tableName
{
FMResultSet *set = [_db executeQuery:@"SELECT count(*) as 'count' FROM sqlite_master WHERE type ='table' and name = ?", tableName];
while ([set next])
{
NSInteger count = [set intForColumn:@"count"];
if (count == 0) {
return NO;
} else {
return YES;
}
}
return NO;
}
- (NSArray *)jq_columnNameArray:(NSString *)tableName
{
return [self getColumnArr:tableName db:_db];
}
- (int)jq_tableItemCount:(NSString *)tableName
{
NSString *sqlstr = [NSString stringWithFormat:@"SELECT count(*) as 'count' FROM %@", tableName];
FMResultSet *set = [_db executeQuery:sqlstr];
while ([set next])
{
return [set intForColumn:@"count"];
}
return 0;
}
- (void)close
{
[_db close];
}
- (void)open
{
[_db open];
}
- (NSInteger)lastInsertPrimaryKeyId:(NSString *)tableName
{
NSString *sqlstr = [NSString stringWithFormat:@"SELECT * FROM %@ where pkid = (SELECT max(pkid) FROM %@)", tableName, tableName];
FMResultSet *set = [_db executeQuery:sqlstr];
while ([set next])
{
return [set longLongIntForColumn:@"pkid"];
}
return 0;
}
- (BOOL)jq_alterTable:(NSString *)tableName dicOrModel:(id)parameters
{
return [self jq_alterTable:tableName dicOrModel:parameters excludeName:nil];
}
- (BOOL)jq_alterTable:(NSString *)tableName dicOrModel:(id)parameters excludeName:(NSArray *)nameArr
{
__block BOOL flag;
[self jq_inTransaction:^(BOOL *rollback) {
if ([parameters isKindOfClass:[NSDictionary class]]) {
for (NSString *key in parameters) {
if ([nameArr containsObject:key]) {
continue;
}
flag = [_db executeUpdate:[NSString stringWithFormat:@"ALTER TABLE %@ ADD COLUMN %@ %@", tableName, key, parameters[key]]];
if (!flag) {
*rollback = YES;
return;
}
}
} else {
Class CLS;
if ([parameters isKindOfClass:[NSString class]]) {
if (!NSClassFromString(parameters)) {
CLS = nil;
} else {
CLS = NSClassFromString(parameters);
}
} else if ([parameters isKindOfClass:[NSObject class]]) {
CLS = [parameters class];
} else {
CLS = parameters;
}
NSDictionary *modelDic = [self modelToDictionary:CLS excludePropertyName:nameArr];
NSArray *columnArr = [self getColumnArr:tableName db:_db];
for (NSString *key in modelDic) {
if (![columnArr containsObject:key] && ![nameArr containsObject:key]) {
flag = [_db executeUpdate:[NSString stringWithFormat:@"ALTER TABLE %@ ADD COLUMN %@ %@", tableName, key, modelDic[key]]];
if (!flag) {
*rollback = YES;
return;
}
}
}
}
}];
return flag;
}
// ============================= 线程安全操作 ===============================
- (void)jq_inDatabase:(void(^)(void))block
{
[[self dbQueue] inDatabase:^(FMDatabase *db) {
block();
}];
}
- (void)jq_inTransaction:(void(^)(BOOL *rollback))block
{
[[self dbQueue] inTransaction:^(FMDatabase *db, BOOL *rollback) {
block(rollback);
}];
}
@end
//
// RNUpdateService.h
// RNMonitor
//
// Created by zhiyu on 17/2/27.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^RNHttpResultBlock)(BOOL success, id data, NSError *error);
@interface RNUpdateService : NSObject
+ (void)POST:(NSString *)URLString
parameters:(id)params
resultBlock:(RNHttpResultBlock)resultBlock;
@end
//
// RNUpdateService.m
// RNMonitor
//
// Created by zhiyu on 17/2/27.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNUpdateService.h"
#import "RNJSON.h"
#import "RNUtil.h"
@implementation RNUpdateService
+ (void)POST:(NSString *)URLString
parameters:(id)params
resultBlock:(RNHttpResultBlock)resultBlock {
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URLString]];
[request setHTTPMethod:@"POST"];
[request setTimeoutInterval:20];
[request setValue:@"IOS" forHTTPHeaderField:@"User-Agent"];
[request setHTTPBody:[[self appendParams:params] dataUsingEncoding:NSUTF8StringEncoding]];
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
resultBlock(NO,nil,error);
return ;
}
NSError *error;
id dict = LPJSONDecode(data, &error);
if ([dict isKindOfClass:[NSDictionary class]]) {
if (dict[@"error"]) {
dispatch_async(dispatch_get_main_queue(), ^{
resultBlock(NO, nil, dict[@"error"]);
});
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
resultBlock(YES, dict, nil);
});
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
resultBlock(YES, nil, nil);
});
});
}] resume];
}
+ (NSString*)appendParams:(id)parama{
NSString *resultString = @"";
if ([parama isKindOfClass:[NSDictionary class]]) {
for (NSString *key in parama) {
NSString *simpleString = @"";
if ([parama[key] isKindOfClass:[NSArray class]]) {
simpleString = [self appendParamsWithArray:parama[key]];
resultString = [NSString stringWithFormat:@"%@%@%@",resultString,resultString.length>0?@"&":@"",simpleString];
}else if ([parama[key] isKindOfClass:[NSDictionary class]]){
simpleString = [self appendParamsWithDict:parama[key]];
resultString = [NSString stringWithFormat:@"%@%@%@=%@",resultString,resultString.length>0?@"&":@"",key,simpleString];
}else if([parama[key] isKindOfClass:[NSString class]]){
simpleString = parama[key];
resultString = [NSString stringWithFormat:@"%@%@%@=%@",resultString,resultString.length>0?@"&":@"",key,simpleString];
}
}
}
return resultString ;
}
+ (NSString*)appendParamsWithDict:(NSDictionary*)dict{
NSString *resultString = @"";
for (NSString*key in dict.allKeys) {
resultString = [NSString stringWithFormat:@"%@%@%@=%@",resultString,resultString.length>0?@"&":@"",key,dict[key]];
}
return resultString;
}
+ (NSString*)appendParamsWithArray:(NSArray*)array {
NSMutableArray *dataArray = [NSMutableArray array];
NSString *result = @"";
for (NSDictionary*dict in array) {
NSString * dataString= @"";
for (NSString*key in dict.allKeys) {
if([dict[key] isKindOfClass:[NSString class]]){
dataString = [NSString stringWithFormat:@"%@%@%@=%@",dataString,dataString.length>0?@"&":@"",key,[self decodeString:dict[key]]];
}
}
result = [NSString stringWithFormat:@"%@%@data=%@",result,result.length>0?@"&":@"",[self decodeString:dataString]];
}
return result;
}
+ (NSString*)decodeString:(NSString*)string{
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
}
@end
/*
Copyright (c) 2011, Tony Million.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
//! Project version number for MacOSReachability.
FOUNDATION_EXPORT double ReachabilityVersionNumber;
//! Project version string for MacOSReachability.
FOUNDATION_EXPORT const unsigned char ReachabilityVersionString[];
/**
* Create NS_ENUM macro if it does not exist on the targeted version of iOS or OS X.
*
* @see http://nshipster.com/ns_enum-ns_options/
**/
#ifndef NS_ENUM
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#endif
extern NSString *const kReachabilityChangedNotification;
typedef NS_ENUM(NSInteger, NetworkStatus) {
// Apple NetworkStatus Compatible Names.
NotReachable = 0,
ReachableViaWiFi = 2,
ReachableViaWWAN = 1
};
@class Reachability;
typedef void (^NetworkReachable)(Reachability * reachability);
typedef void (^NetworkUnreachable)(Reachability * reachability);
typedef void (^NetworkReachability)(Reachability * reachability, SCNetworkConnectionFlags flags);
@interface Reachability : NSObject
@property (nonatomic, copy) NetworkReachable reachableBlock;
@property (nonatomic, copy) NetworkUnreachable unreachableBlock;
@property (nonatomic, copy) NetworkReachability reachabilityBlock;
@property (nonatomic, assign) BOOL reachableOnWWAN;
+(instancetype)reachabilityWithHostname:(NSString*)hostname;
// This is identical to the function above, but is here to maintain
//compatibility with Apples original code. (see .m)
+(instancetype)reachabilityWithHostName:(NSString*)hostname;
+(instancetype)reachabilityForInternetConnection;
+(instancetype)reachabilityWithAddress:(void *)hostAddress;
+(instancetype)reachabilityForLocalWiFi;
-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref;
-(BOOL)startNotifier;
-(void)stopNotifier;
-(BOOL)isReachable;
-(BOOL)isReachableViaWWAN;
-(BOOL)isReachableViaWiFi;
// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired; // Identical DDG variant.
-(BOOL)connectionRequired; // Apple's routine.
// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand;
// Is user intervention required?
-(BOOL)isInterventionRequired;
-(NetworkStatus)currentReachabilityStatus;
-(SCNetworkReachabilityFlags)reachabilityFlags;
-(NSString*)currentReachabilityString;
-(NSString*)currentReachabilityFlags;
@end
/*
Copyright (c) 2011, Tony Million.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#import "Reachability.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
NSString *const kReachabilityChangedNotification = @"kReachabilityChangedNotification";
@interface Reachability ()
@property (nonatomic, assign) SCNetworkReachabilityRef reachabilityRef;
@property (nonatomic, strong) dispatch_queue_t reachabilitySerialQueue;
@property (nonatomic, strong) id reachabilityObject;
-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags;
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags;
@end
static NSString *reachabilityFlags(SCNetworkReachabilityFlags flags)
{
return [NSString stringWithFormat:@"%c%c %c%c%c%c%c%c%c",
#if TARGET_OS_IPHONE
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
#else
'X',
#endif
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-'];
}
// Start listening for reachability notifications on the current run loop
static void TMReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target)
Reachability *reachability = ((__bridge Reachability*)info);
// We probably don't need an autoreleasepool here, as GCD docs state each queue has its own autorelease pool,
// but what the heck eh?
@autoreleasepool
{
[reachability reachabilityChanged:flags];
}
}
@implementation Reachability
#pragma mark - Class Constructor Methods
+(instancetype)reachabilityWithHostName:(NSString*)hostname
{
return [Reachability reachabilityWithHostname:hostname];
}
+(instancetype)reachabilityWithHostname:(NSString*)hostname
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:ref];
return reachability;
}
return nil;
}
+(instancetype)reachabilityWithAddress:(void *)hostAddress
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)hostAddress);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:ref];
return reachability;
}
return nil;
}
+ (instancetype)reachabilityForInternetConnection
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress:&zeroAddress];
}
+(instancetype)reachabilityForLocalWiFi
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
return [self reachabilityWithAddress:&localWifiAddress];
}
// Initialization methods
-(instancetype)initWithReachabilityRef:(SCNetworkReachabilityRef)ref
{
self = [super init];
if (self != nil)
{
self.reachableOnWWAN = YES;
self.reachabilityRef = ref;
// We need to create a serial queue.
// We allocate this once for the lifetime of the notifier.
self.reachabilitySerialQueue = dispatch_queue_create("com.tonymillion.reachability", NULL);
}
return self;
}
-(void)dealloc
{
[self stopNotifier];
if(self.reachabilityRef)
{
CFRelease(self.reachabilityRef);
self.reachabilityRef = nil;
}
self.reachableBlock = nil;
self.unreachableBlock = nil;
self.reachabilityBlock = nil;
self.reachabilitySerialQueue = nil;
}
#pragma mark - Notifier Methods
// Notifier
// NOTE: This uses GCD to trigger the blocks - they *WILL NOT* be called on THE MAIN THREAD
// - In other words DO NOT DO ANY UI UPDATES IN THE BLOCKS.
// INSTEAD USE dispatch_async(dispatch_get_main_queue(), ^{UISTUFF}) (or dispatch_sync if you want)
-(BOOL)startNotifier
{
// allow start notifier to be called multiple times
if(self.reachabilityObject && (self.reachabilityObject == self))
{
return YES;
}
SCNetworkReachabilityContext context = { 0, NULL, NULL, NULL, NULL };
context.info = (__bridge void *)self;
if(SCNetworkReachabilitySetCallback(self.reachabilityRef, TMReachabilityCallback, &context))
{
// Set it as our reachability queue, which will retain the queue
if(SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, self.reachabilitySerialQueue))
{
// this should do a retain on ourself, so as long as we're in notifier mode we shouldn't disappear out from under ourselves
// woah
self.reachabilityObject = self;
return YES;
}
else
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetDispatchQueue() failed: %s", SCErrorString(SCError()));
#endif
// UH OH - FAILURE - stop any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
}
}
else
{
#ifdef DEBUG
NSLog(@"SCNetworkReachabilitySetCallback() failed: %s", SCErrorString(SCError()));
#endif
}
// if we get here we fail at the internet
self.reachabilityObject = nil;
return NO;
}
-(void)stopNotifier
{
// First stop, any callbacks!
SCNetworkReachabilitySetCallback(self.reachabilityRef, NULL, NULL);
// Unregister target from the GCD serial dispatch queue.
SCNetworkReachabilitySetDispatchQueue(self.reachabilityRef, NULL);
self.reachabilityObject = nil;
}
#pragma mark - reachability tests
// This is for the case where you flick the airplane mode;
// you end up getting something like this:
//Reachability: WR ct-----
//Reachability: -- -------
//Reachability: WR ct-----
//Reachability: -- -------
// We treat this as 4 UNREACHABLE triggers - really apple should do better than this
#define testcase (kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)
-(BOOL)isReachableWithFlags:(SCNetworkReachabilityFlags)flags
{
BOOL connectionUP = YES;
if(!(flags & kSCNetworkReachabilityFlagsReachable))
connectionUP = NO;
if( (flags & testcase) == testcase )
connectionUP = NO;
#if TARGET_OS_IPHONE
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
// We're on 3G.
if(!self.reachableOnWWAN)
{
// We don't want to connect when on 3G.
connectionUP = NO;
}
}
#endif
return connectionUP;
}
-(BOOL)isReachable
{
SCNetworkReachabilityFlags flags;
if(!SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
return NO;
return [self isReachableWithFlags:flags];
}
-(BOOL)isReachableViaWWAN
{
#if TARGET_OS_IPHONE
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
// Check we're REACHABLE
if(flags & kSCNetworkReachabilityFlagsReachable)
{
// Now, check we're on WWAN
if(flags & kSCNetworkReachabilityFlagsIsWWAN)
{
return YES;
}
}
}
#endif
return NO;
}
-(BOOL)isReachableViaWiFi
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
// Check we're reachable
if((flags & kSCNetworkReachabilityFlagsReachable))
{
#if TARGET_OS_IPHONE
// Check we're NOT on WWAN
if((flags & kSCNetworkReachabilityFlagsIsWWAN))
{
return NO;
}
#endif
return YES;
}
}
return NO;
}
// WWAN may be available, but not active until a connection has been established.
// WiFi may require a connection for VPN on Demand.
-(BOOL)isConnectionRequired
{
return [self connectionRequired];
}
-(BOOL)connectionRequired
{
SCNetworkReachabilityFlags flags;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}
// Dynamic, on demand connection?
-(BOOL)isConnectionOnDemand
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & (kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand)));
}
return NO;
}
// Is user intervention required?
-(BOOL)isInterventionRequired
{
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return ((flags & kSCNetworkReachabilityFlagsConnectionRequired) &&
(flags & kSCNetworkReachabilityFlagsInterventionRequired));
}
return NO;
}
#pragma mark - reachability status stuff
-(NetworkStatus)currentReachabilityStatus
{
if([self isReachable])
{
if([self isReachableViaWiFi])
return ReachableViaWiFi;
#if TARGET_OS_IPHONE
return ReachableViaWWAN;
#endif
}
return NotReachable;
}
-(SCNetworkReachabilityFlags)reachabilityFlags
{
SCNetworkReachabilityFlags flags = 0;
if(SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags))
{
return flags;
}
return 0;
}
-(NSString*)currentReachabilityString
{
NetworkStatus temp = [self currentReachabilityStatus];
if(temp == ReachableViaWWAN)
{
// Updated for the fact that we have CDMA phones now!
return NSLocalizedString(@"Cellular", @"");
}
if (temp == ReachableViaWiFi)
{
return NSLocalizedString(@"WiFi", @"");
}
return NSLocalizedString(@"No Connection", @"");
}
-(NSString*)currentReachabilityFlags
{
return reachabilityFlags([self reachabilityFlags]);
}
#pragma mark - Callback function calls this method
-(void)reachabilityChanged:(SCNetworkReachabilityFlags)flags
{
if([self isReachableWithFlags:flags])
{
if(self.reachableBlock)
{
self.reachableBlock(self);
}
}
else
{
if(self.unreachableBlock)
{
self.unreachableBlock(self);
}
}
if(self.reachabilityBlock)
{
self.reachabilityBlock(self, flags);
}
// this makes sure the change notification happens on the MAIN THREAD
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kReachabilityChangedNotification
object:self];
});
}
#pragma mark - Debug Description
- (NSString *) description
{
NSString *description = [NSString stringWithFormat:@"<%@: %#x (%@)>",
NSStringFromClass([self class]), (unsigned int) self, [self currentReachabilityFlags]];
return description;
}
@end
//
// IPAddressConfig.h
// IP_Test
//
// Created by 夏远全 on 16/12/23.
// Copyright © 2016年 xiayuanquan. All rights reserved.
//
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/sockio.h>
#include <net/if.h>
#include <errno.h>
#include <net/if_dl.h>
#include <net/ethernet.h>
#include <ifaddrs.h>
#include <arpa/inet.h>
#define BUFFERSIZE 4000
#define MAXADDRS 32
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
@interface IPAddressConfig : NSObject
// extern
extern char *if_names[MAXADDRS];
extern char *ip_names[MAXADDRS];
extern char *hw_addrs[MAXADDRS];
extern unsigned long ip_addrs[MAXADDRS];
// Function prototypes
void InitAddresses();
void FreeAddresses();
void GetIPAddresses();
void GetHWAddresses();
@end
//
// IPAddressConfig.m
// IP_Test
//
// Created by 夏远全 on 16/12/23.
// Copyright © 2016年 xiayuanquan. All rights reserved.
//
#import "IPAddressConfig.h"
@implementation IPAddressConfig
char *if_names[MAXADDRS];
char *ip_names[MAXADDRS];
char *hw_addrs[MAXADDRS];
unsigned long ip_addrs[MAXADDRS];
static int nextAddr = 0;
void InitAddresses()
{
int i;
for (i=0; i<MAXADDRS; ++i)
{
if_names[i] = ip_names[i] = hw_addrs[i] = NULL;
ip_addrs[i] = 0;
}
}
void FreeAddresses()
{
int i;
for (i=0; i<MAXADDRS; ++i)
{
if (if_names[i] != 0) free(if_names[i]);
if (ip_names[i] != 0) free(ip_names[i]);
if (hw_addrs[i] != 0) free(hw_addrs[i]);
ip_addrs[i] = 0;
}
InitAddresses();
}
void GetIPAddresses()
{
int i, len, flags;
char buffer[BUFFERSIZE], *ptr, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sin;
char temp[80];
int sockfd;
for (i=0; i<MAXADDRS; ++i)
{
if_names[i] = ip_names[i] = NULL;
ip_addrs[i] = 0;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket failed");
return;
}
ifc.ifc_len = BUFFERSIZE;
ifc.ifc_buf = buffer;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0)
{
perror("ioctl error");
return;
}
lastname[0] = 0;
for (ptr = buffer; ptr < buffer + ifc.ifc_len; )
{
ifr = (struct ifreq *)ptr;
len = max(sizeof(struct sockaddr), ifr->ifr_addr.sa_len);
ptr += sizeof(ifr->ifr_name) + len; // for next one in buffer
if (ifr->ifr_addr.sa_family != AF_INET)
{
continue; // ignore if not desired address family
}
if ((cptr = (char *)strchr(ifr->ifr_name, ':')) != NULL)
{
*cptr = 0; // replace colon will null
}
if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0)
{
continue; /* already processed this interface */
}
memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
ifrcopy = *ifr;
ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy);
flags = ifrcopy.ifr_flags;
if ((flags & IFF_UP) == 0)
{
continue; // ignore if interface not up
}
if_names[nextAddr] = (char *)malloc(strlen(ifr->ifr_name)+1);
if (if_names[nextAddr] == NULL)
{
return;
}
strcpy(if_names[nextAddr], ifr->ifr_name);
sin = (struct sockaddr_in *)&ifr->ifr_addr;
strcpy(temp, inet_ntoa(sin->sin_addr));
ip_names[nextAddr] = (char *)malloc(strlen(temp)+1);
if (ip_names[nextAddr] == NULL)
{
return;
}
strcpy(ip_names[nextAddr], temp);
ip_addrs[nextAddr] = sin->sin_addr.s_addr;
++nextAddr;
}
close(sockfd);
}
void GetHWAddresses()
{
struct ifconf ifc;
struct ifreq *ifr;
int i, sockfd;
char buffer[BUFFERSIZE], *cp, *cplim;
char temp[80];
for (i=0; i<MAXADDRS; ++i)
{
hw_addrs[i] = NULL;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("socket failed");
return;
}
ifc.ifc_len = BUFFERSIZE;
ifc.ifc_buf = buffer;
if (ioctl(sockfd, SIOCGIFCONF, (char *)&ifc) < 0)
{
perror("ioctl error");
close(sockfd);
return;
}
ifr = ifc.ifc_req;
cplim = buffer + ifc.ifc_len;
for (cp=buffer; cp < cplim; )
{
ifr = (struct ifreq *)cp;
if (ifr->ifr_addr.sa_family == AF_LINK)
{
struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
int a,b,c,d,e,f;
int i;
strcpy(temp, (char *)ether_ntoa((const struct ether_addr *)LLADDR(sdl)));
sscanf(temp, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);
sprintf(temp, "%02X:%02X:%02X:%02X:%02X:%02X",a,b,c,d,e,f);
for (i=0; i<MAXADDRS; ++i)
{
if ((if_names[i] != NULL) && (strcmp(ifr->ifr_name, if_names[i]) == 0))
{
if (hw_addrs[i] == NULL)
{
hw_addrs[i] = (char *)malloc(strlen(temp)+1);
strcpy(hw_addrs[i], temp);
break;
}
}
}
}
cp += sizeof(ifr->ifr_name) + max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
}
close(sockfd);
}
@end
//
// IPToolManager.h
// BiaoJiePay
//
// Created by 夏远全 on 16/11/22.
// Copyright © 2016年 xiayuanquan. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface IPToolManager : NSObject
/**
* 单例
*/
+(instancetype)sharedManager;
/**
* 方法一
* 获取具体的ip地址
*/
-(NSString *)currentIpAddress;
/**
* 方法二
* 获取ip地址的详细信息
*/
-(void)currentIPAdressDetailInfo;
- (NSString *)deviceWANIPAddress;
@end
//
// IPToolManager.m
// BiaoJiePay
//
// Created by 夏远全 on 16/11/22.
// Copyright © 2016年 xiayuanquan. All rights reserved.
//
#import "IPToolManager.h"
#import "IPAddressConfig.h"
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
#pragma mark IPv4是32位地址长度
#pragma mark IPv6是128位地址长度
@implementation IPToolManager
+(instancetype)sharedManager{
static dispatch_once_t onceToken;
static IPToolManager *instance = nil;
dispatch_once(&onceToken, ^{
instance = [[IPToolManager alloc] init];
});
return instance;
}
#pragma mark - 方法一
-(NSString *)currentIpAddress{
return [self getIPAddress:YES];
}
- (NSString *)getIPAddress:(BOOL)preferIPv4
{
NSArray *searchArray = preferIPv4 ?
@[ IOS_WIFI @"/" IP_ADDR_IPv4, IOS_WIFI @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6,IOS_VPN @"/" IP_ADDR_IPv4, IOS_VPN @"/" IP_ADDR_IPv6, ] :
@[ IOS_WIFI @"/" IP_ADDR_IPv6, IOS_WIFI @"/" IP_ADDR_IPv4, IOS_CELLULAR @"/" IP_ADDR_IPv6, IOS_CELLULAR @"/" IP_ADDR_IPv4,IOS_VPN @"/" IP_ADDR_IPv6, IOS_VPN @"/" IP_ADDR_IPv4, ];
NSDictionary *addresses = [self getIPAddresses];
NSLog(@"addresses: %@", addresses);
__block NSString *address;
[searchArray enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL *stop)
{
address = addresses[key];
if(address) *stop = YES;
} ];
return address ? address : @"0.0.0.0";
}
- (NSDictionary *)getIPAddresses
{
NSMutableDictionary *addresses = [NSMutableDictionary dictionaryWithCapacity:8];
// retrieve the current interfaces - returns 0 on success
struct ifaddrs *interfaces;
if(!getifaddrs(&interfaces)) {
// Loop through linked list of interfaces
struct ifaddrs *interface;
for(interface=interfaces; interface; interface=interface->ifa_next) {
if(!(interface->ifa_flags & IFF_UP) /* || (interface->ifa_flags & IFF_LOOPBACK) */ ) {
continue; // deeply nested code harder to read
}
const struct sockaddr_in *addr = (const struct sockaddr_in*)interface->ifa_addr;
char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
if(addr && (addr->sin_family==AF_INET || addr->sin_family==AF_INET6)) {
NSString *name = [NSString stringWithUTF8String:interface->ifa_name];
NSString *type;
if(addr->sin_family == AF_INET) {
if(inet_ntop(AF_INET, &addr->sin_addr, addrBuf, INET_ADDRSTRLEN)) {
type = IP_ADDR_IPv4;
}
} else {
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6*)interface->ifa_addr;
if(inet_ntop(AF_INET6, &addr6->sin6_addr, addrBuf, INET6_ADDRSTRLEN)) {
type = IP_ADDR_IPv6;
}
}
if(type) {
NSString *key = [NSString stringWithFormat:@"%@/%@", name, type];
addresses[key] = [NSString stringWithUTF8String:addrBuf];
}
}
}
// Free memory
freeifaddrs(interfaces);
}
return [addresses count] ? addresses : nil;
}
#pragma mark - 方法二
-(void)currentIPAdressDetailInfo{
InitAddresses();
GetIPAddresses();
GetHWAddresses();
int i;
//NSString *deviceIP = nil;
for (i=0; i<MAXADDRS; ++i)
{
static unsigned long localHost = 0x7F000001; // 127.0.0.1
unsigned long theAddr;
theAddr = ip_addrs[i];
if (theAddr == 0) break;
if (theAddr == localHost) continue;
NSLog(@"Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);
}
}
- (NSString *)deviceWANIPAddress
{
NSURL *ipURL = [NSURL URLWithString:@"http://ip.taobao.com/service/getIpInfo.php?ip=myip"];
NSData *data = [NSData dataWithContentsOfURL:ipURL];
NSDictionary *ipDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
return (ipDic[@"data"][@"ip"] ? ipDic[@"data"][@"ip"] : @"");
}
@end
//
// LPCoreDatamanager.h
// demo
//
// Created by zhiyu on 17/2/23.
// Copyright © 2017年 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface LPCoreDatamanager : NSObject
/**
* 获取数据库存储的路径
*/
@property (nonatomic,copy,readonly) NSString *sqlPath;
/**
* 获取.xcdatamodeld文件的名称
*/
@property (nonatomic,copy,readonly) NSString *modelName;
/**
* 获取.xcdatamodeld文件中创建的实体的名称
*/
@property (nonatomic,copy,readonly) NSString *entityName;
/**
* 创建CoreData数据库
*
* @param entityName 实体名称
* @param modelName .xcdatamodeld文件名称(为nil则主动从程序包加载模型文件)
* @param sqlPath 数据库存储的路径
* @param success 成功回调
* @param fail 失败回调
*
* @return 返回CoreDataAPI对象
*/
- (instancetype)initWithCoreData:(NSString *)entityName modelName:(NSString *)modelName sqlPath:(NSString *)sqlPath success:(void(^)(void))success fail:(void(^)(NSError *error))fail;
/**
* 插入数据
*
* @param dict 字典中的键值对必须要与实体中的每个名字一一对应
* @param success 成功回调
* @param fail 失败回调
*/
- (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail;
/**
* 查询数据
*
* @param sequenceKeys 数组高级排序(数组里存放实体中的key,顺序按自己需要的先后存放即可),实体key来排序
* @param isAscending 是否上升排序
* @param filterStr 过滤语句
* @param success 成功后结果回调
* @param fail 失败回调
*/
- (void)readEntity:(NSArray *)sequenceKeys ascending:(BOOL)isAscending filterStr:(NSString *)filterStr success:(void(^)(NSArray *results))success fail:(void(^)(NSError *error))fail;
/**
* 删除数据
*
* @param entity NSManagedObject
* @param success 成功回调
* @param fail 失败回调
*/
- (void)deleteEntity:(NSManagedObject *)entity success:(void(^)(void))success fail:(void(^)(NSError *error))fail;
/**
* 更新数据
*
* @param success 成功回调
* @param fail 失败回调
*/
- (void)updateEntity:(void(^)(void))success fail:(void(^)(NSError *error))fail;
@end
//
// LPCoreDatamanager.m
// demo
//
// Created by zhiyu on 17/2/23.
// Copyright © 2017年 terminus. All rights reserved.
//
#import "LPCoreDatamanager.h"
@interface LPCoreDatamanager()
/**
* 数据模型对象
*/
@property (nonatomic,strong) NSManagedObjectModel *model;
/**
* 上下文
*/
@property (nonatomic,strong) NSManagedObjectContext *context;
/**
* 持久性存储区
*/
@property (nonatomic,strong) NSPersistentStoreCoordinator *persistent;
@end
@implementation LPCoreDatamanager
- (instancetype)initWithCoreData:(NSString *)entityName modelName:(NSString *)modelName sqlPath:(NSString *)sqlPath success:(void(^)(void))success fail:(void(^)(NSError *error))fail
{
if (self = [super init]) {
_entityName = entityName;
_modelName = modelName;
_sqlPath = sqlPath;
self.context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
if (modelName) {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"RNMonitor" withExtension:@"mom"];
self.model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
} else {
self.model = [NSManagedObjectModel mergedModelFromBundles:nil];
}
self.persistent = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.model];
NSError *error = nil;
[self.persistent addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlPath] options:nil error:&error];
if (error) {
if (fail) {
fail(error);
}
} else {
self.context.persistentStoreCoordinator = self.persistent;
if (success) {
success();
}
}
}
return self;
}
// 添加数据
- (void)insertNewEntity:(NSDictionary *)dict success:(void(^)(void))success fail:(void(^)(NSError *error))fail
{
if (!dict||dict.allKeys.count == 0) return;
NSManagedObject *newEntity = [NSEntityDescription insertNewObjectForEntityForName:self.entityName inManagedObjectContext:self.context];
for (NSString *key in [dict allKeys]) {
[newEntity setValue:[dict objectForKey:key] forKey:key];
}
NSError *error = nil;
BOOL result = [self.context save:&error];
if (!result) {
if (fail) {
fail(error);
}
} else {
if (success) {
success();
}
}
}
// 查询数据
- (void)readEntity:(NSArray *)sequenceKeys ascending:(BOOL)isAscending filterStr:(NSString *)filterStr success:(void(^)(NSArray *results))success fail:(void(^)(NSError *error))fail
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *desc = [NSEntityDescription entityForName:self.entityName inManagedObjectContext:self.context];
request.entity = desc;
if (sequenceKeys&&sequenceKeys.count>0) {
NSMutableArray *array = [NSMutableArray array];
for (NSString *key in sequenceKeys) {
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:key ascending:isAscending];
[array addObject:sort];
}
if (array.count>0) {
request.sortDescriptors = array;
}
}
if (filterStr) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:filterStr];
request.predicate = predicate;
}
NSError *error = nil;
NSArray *objs = [self.context executeFetchRequest:request error:&error];
if (error) {
if (fail) {
fail(error);
}
} else{
if (success) {
success(objs);
}
}
}
// 更新数据
- (void)updateEntity:(void(^)(void))success fail:(void(^)(NSError *error))fail
{
NSError *error = nil;
[self.context save:&error];
if (error) {
if (fail) {
fail(error);
}
} else {
if (success) {
success();
}
}
}
// 删除数据
- (void)deleteEntity:(NSManagedObject *)entity success:(void(^)(void))success fail:(void(^)(NSError *error))fail
{
[self.context deleteObject:entity];
NSError *error = nil;
[self.context save:&error];
if (error) {
if (fail) {
fail(error);
}
} else {
if (success) {
success();
}
}
}
@end
//
// Created by Allen Chiang on 16/3/17.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSObject (RNMIU_ToDictionary)
- (NSDictionary *)RNMIU_ToDictionary;
- (NSDictionary *)RNMIU_ToDictionaryWithDepth:(NSInteger)depth;
@end
//
// Created by Allen Chiang on 16/3/17.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import <objc/runtime.h>
#import <objc/message.h>
#import "NSObject+RNMIU_ToDictionary.h"
#import "RNMIUConvertDefine.h"
@implementation NSObject (RNMIU_ToDictionary)
- (NSDictionary *)RNMIU_ToDictionary {
if ([self isKindOfClass:[NSDictionary class]]) {
return (NSDictionary *)self;
}
return [self toDictionaryOrArrayWithDepth:8];
}
- (NSDictionary *)RNMIU_ToDictionaryWithDepth:(NSInteger)depth{
return [self toDictionaryOrArrayWithDepth:depth];
}
- (id)toDictionaryOrArrayWithDepth:(NSUInteger)depth {
if ([self isKindOfClass:[NSArray class]] || [self isKindOfClass:[NSSet class]]) {
id selfObj = self;
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[selfObj count]];
if (depth > 0) {
for (id o in selfObj) {
[array addObject:[o toDictionaryOrArrayWithDepth:depth - 1]];
}
}
return array;
} else if ([self isKindOfClass:[NSDictionary class]]) {
NSDictionary *selfObj = (NSDictionary *) self;
NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithCapacity:[selfObj count]];
if (depth > 0) {
[selfObj enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[dic setObject:[obj toDictionaryOrArrayWithDepth:depth - 1]
forKey:key];
}];
}
return dic;
} else if ([self isKindOfClass:[NSNull class]] || [self isKindOfClass:[NSNumber class]]
|| [self isKindOfClass:[NSString class]]) {
return self;
} else if (self == nil) {
return [NSNull null];
} else {
NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithCapacity:10];
Class clazz = [self class];
[RNMPropertyAttributeInfo enumerateClassProperties:clazz
withInfoBlock:^(Class oriClass, Class currentClass, RNMPropertyAttributeInfo *info) {
[self getPropertyToDictionary:dic
pProperty:info
withDepth:depth
withClass:clazz];
}];
return dic;
}
}
- (void)getPropertyToDictionary:(NSMutableDictionary *)dictionary
pProperty:(RNMPropertyAttributeInfo *)attributeInfo
withDepth:(NSUInteger)depth
withClass:(Class)clazz {
if (attributeInfo.transient) {
//不需要对这个字段进行序列化
return;
}
SEL getter = attributeInfo.getter;
id retForId = nil;
char retForChar;
unsigned char retForUnsignedChar;
bool retForBool;
double retForDouble;
int retForInt;
float retForFloat;
long retForLong;
unsigned long retForUnsignedLong;
long long retForLongLong;
unsigned long long retForUnsignedLongLong;
short retForShort;
unsigned short retForUnsignedShort;
unsigned retForUnsigned;
switch (attributeInfo.type) {
case RNMIU_CHAR:
retForChar = ((char ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithChar:retForChar]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_UNSIGNED_CHAR:
retForUnsignedChar = ((unsigned char ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithUnsignedChar:retForUnsignedChar]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_C_BOOL:
retForBool = ((bool ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithBool:retForBool]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_DOUBLE:
retForDouble = ((double ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithDouble:retForDouble]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_INT:
retForInt = ((int ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithInt:retForInt]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_FLOAT:
retForFloat = ((float ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithFloat:retForFloat]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_LONG:
retForLong = ((long ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithLong:retForLong]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_UNSIGNED_LONG:
retForUnsignedLong = ((unsigned long ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithUnsignedLong:retForUnsignedLong]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_LONG_LONG:
retForLongLong = ((long long ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithLongLong:retForLongLong]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_UNSIGNED_LONG_LONG:
retForUnsignedLongLong = ((unsigned long long ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithUnsignedLongLong:retForUnsignedLongLong]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_SHORT:
retForShort = ((short ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithShort:retForShort]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_UNSIGNED_SHORT:
retForUnsignedShort = ((unsigned short ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithUnsignedShort:retForUnsignedShort]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_UNSIGNED:
retForUnsigned = ((unsigned ( *)(id, SEL)) objc_msgSend)(self, getter);
[dictionary setObject:[NSNumber numberWithUnsignedInt:retForUnsigned]
forKey:attributeInfo.dicPropertyName];
return;
case RNMIU_ID:
retForId = ((id ( *)(id, SEL)) objc_msgSend)(self, getter);
if (retForId) {
if ([retForId isKindOfClass:[NSString class]] || [retForId isKindOfClass:[NSNumber class]]) {
[dictionary setObject:retForId
forKey:attributeInfo.dicPropertyName];
} else {
if (depth == 0) {
return;
}
[dictionary setObject:[retForId toDictionaryOrArrayWithDepth:depth - 1]
forKey:attributeInfo
.dicPropertyName];
}
}
return;
default:
break;
}
}
@end
//
// RNDataManager.h
// RNMonitor
//
// Created by zhiyu on 17/2/26.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface RNDataManager : NSObject
+ (NSString*)creatDataWithFileName:(NSString*)name;
+ (BOOL)insertData:(id)data withPath:(NSString*)path;
+ (id)readData:(NSString*)path;
+ (BOOL)removeData:(NSString*)path;
@end
//
// RNDataManager.m
// RNMonitor
//
// Created by zhiyu on 17/2/26.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNDataManager.h"
@implementation RNDataManager
+ (NSString *)creatDataWithFileName:(NSString *)name {
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dataPath =[NSString stringWithFormat:@"%@/%@.plist",docPath,name];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) {
[[NSFileManager defaultManager] createFileAtPath:dataPath contents:nil attributes:nil];
}
return dataPath;
}
+ (BOOL)insertData:(id)data withPath:(NSString *)path
{
if (!data) {
return NO;
}
NSMutableArray *array = [self readData:path];
if (!array) {
array = [NSMutableArray array];
}
[array addObject:data];
return [array writeToFile:path atomically:YES];
}
+ (id)readData:(NSString *)path
{
return [NSMutableArray arrayWithContentsOfFile:path];
}
+ (BOOL)removeData:(NSString *)path
{
NSMutableArray *array = [self readData:path];
[array removeAllObjects];
return [array writeToFile:path atomically:YES];
}
@end
//
// RNDevice.h
// Laplata
//
// Created by zhiyu on 16/9/13.
// Copyright © 2016年 terminus. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RNDevice : UIDevice
/** iOS 设备型号 */
+ (NSString *)iphoneType;
/** 分辨率 */
+ (NSString *)iphoneResolution;
/** 版本号 */
+ (NSString *)appVersion;
/** bundle ID */
+ (NSString *)bundleId;
/** device ID */
+ (NSString *)deviceId;
/** 网络 */
+ (NSString *)iphoneNetState;
/** ip地址 */
+ (NSString *)iphoneIPAddress;
/** 是否越狱 */
+ (BOOL)iphoneIsJailbreak;
/** 系统版本 */
+ (NSString*)iphoneSystemVersion;
/** cpu使用 */
+ (float)iphoneCpuUsage;
/** 内存占用 */
+ (double)iphoneUsedMemory;
/** 磁盘空间 */
+ (NSString *)diskOfAllSizeMBytes;
/** 可用内存*/
+ (NSString *)availableMemory;
/** cpu类型 (待优化)*/
+ (NSString *)cpuType;
/** sdk最低支持版本 (待优化)*/
+ (NSString*)minimumSystemVersion;
@end
//
// RNDevice.m
// Laplata
//
// Created by zhiyu on 16/9/13.
// Copyright © 2016年 terminus. All rights reserved.
//
#import "RNDevice.h"
#import <sys/utsname.h>
#import <ifaddrs.h>
#import <arpa/inet.h>
#import <net/if.h>
#import <mach/mach.h>
#import "IPToolManager.h"
#include <sys/sysctl.h>
#import <objc/message.h>
#import <objc/runtime.h>
#import "Reachability.h"
#define IOS_CELLULAR @"pdp_ip0"
#define IOS_WIFI @"en0"
#define IOS_VPN @"utun0"
#define IP_ADDR_IPv4 @"ipv4"
#define IP_ADDR_IPv6 @"ipv6"
@implementation RNDevice
+ (NSString *)iphoneType {
struct utsname systemInfo;
uname(&systemInfo);
NSString *deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
//iPhone 系列
if ([deviceModel isEqualToString:@"iPhone1,1"]) return @"iPhone 1G";
if ([deviceModel isEqualToString:@"iPhone1,2"]) return @"iPhone 3G";
if ([deviceModel isEqualToString:@"iPhone2,1"]) return @"iPhone 3GS";
if ([deviceModel isEqualToString:@"iPhone3,1"]) return @"iPhone 4";
if ([deviceModel isEqualToString:@"iPhone3,2"]) return @"Verizon iPhone 4";
if ([deviceModel isEqualToString:@"iPhone4,1"]) return @"iPhone 4S";
if ([deviceModel isEqualToString:@"iPhone5,1"]) return @"iPhone 5";
if ([deviceModel isEqualToString:@"iPhone5,2"]) return @"iPhone 5";
if ([deviceModel isEqualToString:@"iPhone5,3"]) return @"iPhone 5C";
if ([deviceModel isEqualToString:@"iPhone5,4"]) return @"iPhone 5C";
if ([deviceModel isEqualToString:@"iPhone6,1"]) return @"iPhone 5S";
if ([deviceModel isEqualToString:@"iPhone6,2"]) return @"iPhone 5S";
if ([deviceModel isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus";
if ([deviceModel isEqualToString:@"iPhone7,2"]) return @"iPhone 6";
if ([deviceModel isEqualToString:@"iPhone8,1"]) return @"iPhone 6s";
if ([deviceModel isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus";
if ([deviceModel isEqualToString:@"iPhone9,1"]) return @"iPhone 7 (CDMA)";
if ([deviceModel isEqualToString:@"iPhone9,3"]) return @"iPhone 7 (GSM)";
if ([deviceModel isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus (CDMA)";
if ([deviceModel isEqualToString:@"iPhone9,4"]) return @"iPhone 7 Plus (GSM)";
if ([deviceModel isEqualToString:@"iPhone10,1"]) return @"iPhone 8";
if ([deviceModel isEqualToString:@"iPhone10,4"]) return @"iPhone 8";
if ([deviceModel isEqualToString:@"iPhone10,2"]) return @"iPhone 8";
if ([deviceModel isEqualToString:@"iPhone10,5"]) return @"iPhone 8";
if ([deviceModel isEqualToString:@"iPhone10,3"]) return @"iPhone X";
if ([deviceModel isEqualToString:@"iPhone10,6"]) return @"iPhone X";
if ([deviceModel isEqualToString:@"iPhone10,7"]) return @"iPhone X";
//iPod 系列
if ([deviceModel isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G";
if ([deviceModel isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G";
if ([deviceModel isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G";
if ([deviceModel isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G";
if ([deviceModel isEqualToString:@"iPod5,1"]) return @"iPod Touch 5G";
//iPad 系列
if ([deviceModel isEqualToString:@"iPad1,1"]) return @"iPad";
if ([deviceModel isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)";
if ([deviceModel isEqualToString:@"iPad2,2"]) return @"iPad 2 (GSM)";
if ([deviceModel isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)";
if ([deviceModel isEqualToString:@"iPad2,4"]) return @"iPad 2 (32nm)";
if ([deviceModel isEqualToString:@"iPad2,5"]) return @"iPad mini (WiFi)";
if ([deviceModel isEqualToString:@"iPad2,6"]) return @"iPad mini (GSM)";
if ([deviceModel isEqualToString:@"iPad2,7"]) return @"iPad mini (CDMA)";
if ([deviceModel isEqualToString:@"iPad3,1"]) return @"iPad 3(WiFi)";
if ([deviceModel isEqualToString:@"iPad3,2"]) return @"iPad 3(CDMA)";
if ([deviceModel isEqualToString:@"iPad3,3"]) return @"iPad 3(4G)";
if ([deviceModel isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)";
if ([deviceModel isEqualToString:@"iPad3,5"]) return @"iPad 4 (4G)";
if ([deviceModel isEqualToString:@"iPad3,6"]) return @"iPad 4 (CDMA)";
if ([deviceModel isEqualToString:@"iPad4,1"]) return @"iPad Air";
if ([deviceModel isEqualToString:@"iPad4,2"]) return @"iPad Air";
if ([deviceModel isEqualToString:@"iPad4,3"]) return @"iPad Air";
if ([deviceModel isEqualToString:@"iPad5,3"]) return @"iPad Air 2";
if ([deviceModel isEqualToString:@"iPad5,4"]) return @"iPad Air 2";
if ([deviceModel isEqualToString:@"i386"]) return @"Simulator";
if ([deviceModel isEqualToString:@"x86_64"]) return @"Simulator";
if ([deviceModel isEqualToString:@"iPad4,4"]
||[deviceModel isEqualToString:@"iPad4,5"]
||[deviceModel isEqualToString:@"iPad4,6"]) return @"iPad mini 2";
if ([deviceModel isEqualToString:@"iPad4,7"]
||[deviceModel isEqualToString:@"iPad4,8"]
||[deviceModel isEqualToString:@"iPad4,9"]) return @"iPad mini 3";
return deviceModel;
}
+ (NSString *)iphoneResolution {
CGRect rect_screen = [[UIScreen mainScreen] bounds];
CGSize size_screen = rect_screen.size;
CGFloat scale_screen = [UIScreen mainScreen].scale;
CGFloat widthResolution = size_screen.width * scale_screen;
CGFloat heightResolution = size_screen.height * scale_screen;
NSString * resolution = [NSString stringWithFormat:@"%.0fx%.0f",heightResolution,widthResolution];
return resolution;
}
+ (NSString *)appVersion {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
}
+ (NSString *)bundleId {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
}
+ (NSString *)iphoneNetState{
Reachability *reach = [Reachability reachabilityForInternetConnection];
NetworkStatus status =[reach currentReachabilityStatus];
switch (status) {
case NotReachable:
return @"offline";
//无网模式
break;
case ReachableViaWWAN:
return @"4G";
break;
case ReachableViaWiFi:
return @"wifi";
break;
default:
return @"unknow";
break;
}
}
+ (NSString *)iphoneIPAddress {
return [[IPToolManager sharedManager] currentIpAddress];
}
+ (BOOL)iphoneIsJailbreak{
NSArray *paths = @[@"/Applications/Cydia.app",
@"/private/var/lib/apt/",
@"/private/var/lib/cydia",
@"/private/var/stash"];
for (NSString *path in paths) {
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) return YES;
}
FILE *bash = fopen("/bin/bash", "r");
if (bash != NULL) {
fclose(bash);
return YES;
}
NSString *path = [NSString stringWithFormat:@"/private/%@", [self stringWithUUID]];
if ([@"test" writeToFile : path atomically : YES encoding : NSUTF8StringEncoding error : NULL]) {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
return YES;
}
return NO;
}
+ (NSString *)stringWithUUID {
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
return (__bridge_transfer NSString *)string;
}
+ (NSString*)deviceId {
return [[UIDevice currentDevice] identifierForVendor].UUIDString;
}
+ (NSString*)iphoneSystemVersion{
return [[UIDevice currentDevice] systemVersion];
}
+ (float)iphoneCpuUsage {
kern_return_t kr;
task_info_data_t tinfo;
mach_msg_type_number_t task_info_count;
task_info_count = TASK_INFO_MAX;
kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
if (kr != KERN_SUCCESS) {
return -1;
}
task_basic_info_t basic_info;
thread_array_t thread_list;
mach_msg_type_number_t thread_count;
thread_info_data_t thinfo;
mach_msg_type_number_t thread_info_count;
thread_basic_info_t basic_info_th;
uint32_t stat_thread = 0; // Mach threads
basic_info = (task_basic_info_t)tinfo;
// get threads in the task
kr = task_threads(mach_task_self(), &thread_list, &thread_count);
if (kr != KERN_SUCCESS) {
return -1;
}
if (thread_count > 0)
stat_thread += thread_count;
long tot_sec = 0;
long tot_usec = 0;
float tot_cpu = 0;
int j;
for (j = 0; j < thread_count; j++)
{
thread_info_count = THREAD_INFO_MAX;
kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
(thread_info_t)thinfo, &thread_info_count);
if (kr != KERN_SUCCESS) {
return -1;
}
basic_info_th = (thread_basic_info_t)thinfo;
if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
}
} // for each thread
kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
assert(kr == KERN_SUCCESS);
NSLog(@"cpu%f",tot_cpu);
return tot_cpu;
}
+ (float)iphoneUsedMemory {
task_basic_info_data_t taskInfo;
mach_msg_type_number_t infoCount =TASK_BASIC_INFO_COUNT;
kern_return_t kernReturn =task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&taskInfo,
&infoCount);
if (kernReturn != KERN_SUCCESS) {
return NSNotFound;
}
NSLog(@"mem%f",taskInfo.resident_size / 1024.0 / 1024.0);
return taskInfo.resident_size / 1024.0 / 1024.0;
}
//磁盘总空间
+ (NSString *)diskOfAllSizeMBytes {
CGFloat size = 0.0;
NSError *error;
NSDictionary *dic = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error];
if (error) {
#ifdef DEBUG
NSLog(@"error: %@", error.localizedDescription);
#endif
}else{
NSNumber *number = [dic objectForKey:NSFileSystemSize];
size = [number floatValue]/1024/1024;
}
return [NSString stringWithFormat:@"%f",size] ;
}
// 获取当前设备可用内存(单位:MB)
+ (NSString *)availableMemory {
vm_statistics_data_t vmStats;
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(),
HOST_VM_INFO,
(host_info_t)&vmStats,
&infoCount);
if (kernReturn != KERN_SUCCESS) {
return NULL;
}
return [NSString stringWithFormat:@"%ld",((vm_page_size *vmStats.free_count) / 1024.0) / 1024.0] ;
}
+ (NSString *)cpuType{
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
NSMutableString *cpu = [[NSMutableString alloc] init];
cpu_type_t type;
cpu_subtype_t subtype;
size = sizeof(type);
sysctlbyname("hw.cputype", &type, &size, NULL, 0);
size = sizeof(subtype);
sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0);
// values for cputype and cpusubtype defined in mach/machine.h
if (type == CPU_TYPE_X86)
{
[cpu appendString:@"x86 "];
// check for subtype ...
} else if (type == CPU_TYPE_ARM)
{
[cpu appendString:@"ARM"];
switch(subtype)
{
case CPU_SUBTYPE_ARM_V7:
[cpu appendString:@"V7"];
break;
case CPU_SUBTYPE_ARM_V7S:
[cpu appendString:@"V7s"];
break;
}
}
return cpu;
}
+ (NSString*)minimumSystemVersion{
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"LSMinimumSystemVersion"];
}
+ (NSArray *)getAllProperties:(id)propertie
{
u_int count;
objc_property_t *properties =class_copyPropertyList([propertie class], &count);
NSMutableArray *propertiesArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i<count; i++)
{
const char* propertyName =property_getName(properties[i]);
[propertiesArray addObject: [NSString stringWithUTF8String: propertyName]];
}
free(properties);
return propertiesArray;
}
@end
//
// Created by Allen Chiang on 16/3/2.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
extern NSData *LPJSONEncode(id object, NSError **error);
extern id LPJSONDecode(NSData *data, NSError **error);
//
// Created by Allen Chiang on 16/3/2.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import "RNJSON.h"
NSData *LPJSONEncode(id object, NSError **error) {
__autoreleasing NSData *data = nil;
SEL _JSONKitSelector = NSSelectorFromString(@"JSONDataWithOptions:error:");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONString");
id _SBJsonWriterClass = NSClassFromString(@"SBJsonWriter");
SEL _SBJsonWriterSelector = NSSelectorFromString(@"dataWithObject:");
id _NXJsonSerializerClass = NSClassFromString(@"NXJsonSerializer");
SEL _NXJsonSerializerSelector = NSSelectorFromString(@"serialize:");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"dataWithJSONObject:options:error:");
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&object
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger writeOptions = 0;
[invocation setArgument:&writeOptions
atIndex:3];
if (error != NULL) {
[invocation setArgument:error
atIndex:4];
}
[invocation invoke];
[invocation getReturnValue:&data];
} else if (_JSONKitSelector && [object respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_JSONKitSelector]];
invocation.target = object;
invocation.selector = _JSONKitSelector;
NSUInteger serializeOptionFlags = 0;
[invocation setArgument:&serializeOptionFlags
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
if (error != NULL) {
[invocation setArgument:error
atIndex:3];
}
[invocation invoke];
[invocation getReturnValue:&data];
} else if (_SBJsonWriterClass && [_SBJsonWriterClass instancesRespondToSelector:_SBJsonWriterSelector]) {
id writer = [[_SBJsonWriterClass alloc] init];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[writer methodSignatureForSelector:_SBJsonWriterSelector]];
invocation.target = writer;
invocation.selector = _SBJsonWriterSelector;
[invocation setArgument:&object
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation invoke];
[invocation getReturnValue:&data];
} else if (_YAJLSelector && [object respondsToSelector:_YAJLSelector]) {
@try {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:_YAJLSelector]];
invocation.target = object;
invocation.selector = _YAJLSelector;
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
}
@catch (NSException *exception) {
if (error != NULL) {
*error = [[NSError alloc]
initWithDomain:NSStringFromClass([exception class])
code:0
userInfo:[exception userInfo]];
}
}
} else if (_NXJsonSerializerClass && [_NXJsonSerializerClass respondsToSelector:_NXJsonSerializerSelector]) {
NSString *JSONString = nil;
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NXJsonSerializerClass methodSignatureForSelector:_NXJsonSerializerSelector]];
invocation.target = _NXJsonSerializerClass;
invocation.selector = _NXJsonSerializerSelector;
[invocation setArgument:&object
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation invoke];
[invocation getReturnValue:&JSONString];
data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil)
forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException
reason:NSLocalizedString(@"No JSON generation functionality available", nil)
userInfo:userInfo] raise];
}
return data;
}
id LPJSONDecode(NSData *data, NSError **error) {
__autoreleasing id JSON = nil;
SEL _JSONKitSelector = NSSelectorFromString(@"objectFromJSONDataWithParseOptions:error:");
SEL _YAJLSelector = NSSelectorFromString(@"yajl_JSONWithOptions:error:");
id _SBJSONParserClass = NSClassFromString(@"SBJsonParser");
SEL _SBJSONParserSelector = NSSelectorFromString(@"objectWithData:");
id _NSJSONSerializationClass = NSClassFromString(@"NSJSONSerialization");
SEL _NSJSONSerializationSelector = NSSelectorFromString(@"JSONObjectWithData:options:error:");
id _NXJsonParserClass = NSClassFromString(@"NXJsonParser");
SEL _NXJsonParserSelector = NSSelectorFromString(@"parseData:error:ignoreNulls:");
if (_NSJSONSerializationClass && [_NSJSONSerializationClass respondsToSelector:_NSJSONSerializationSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NSJSONSerializationClass methodSignatureForSelector:_NSJSONSerializationSelector]];
invocation.target = _NSJSONSerializationClass;
invocation.selector = _NSJSONSerializationSelector;
[invocation setArgument:&data
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
NSUInteger readOptions = 0;
[invocation setArgument:&readOptions
atIndex:3];
if (error != NULL) {
[invocation setArgument:&error
atIndex:4];
}
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_JSONKitSelector && [data respondsToSelector:_JSONKitSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_JSONKitSelector]];
invocation.target = data;
invocation.selector = _JSONKitSelector;
NSUInteger parseOptionFlags = 0;
[invocation setArgument:&parseOptionFlags
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
if (error != NULL) {
[invocation setArgument:&error
atIndex:3];
}
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_SBJSONParserClass && [_SBJSONParserClass instancesRespondToSelector:_SBJSONParserSelector]) {
id parser = [[_SBJSONParserClass alloc] init];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[parser methodSignatureForSelector:_SBJSONParserSelector]];
invocation.target = parser;
invocation.selector = _SBJSONParserSelector;
[invocation setArgument:&data
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_YAJLSelector && [data respondsToSelector:_YAJLSelector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[data methodSignatureForSelector:_YAJLSelector]];
invocation.target = data;
invocation.selector = _YAJLSelector;
NSUInteger yajlParserOptions = 0;
[invocation setArgument:&yajlParserOptions
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
if (error != NULL) {
[invocation setArgument:&error
atIndex:3];
}
[invocation invoke];
[invocation getReturnValue:&JSON];
} else if (_NXJsonParserClass && [_NXJsonParserClass respondsToSelector:_NXJsonParserSelector]) {
NSNumber *nullOption = [NSNumber numberWithBool:YES];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[_NXJsonParserClass methodSignatureForSelector:_NXJsonParserSelector]];
invocation.target = _NXJsonParserClass;
invocation.selector = _NXJsonParserSelector;
[invocation setArgument:&data
atIndex:2]; // arguments 0 and 1 are self and _cmd respectively, automatically set by NSInvocation
if (error != NULL) {
[invocation setArgument:&error
atIndex:3];
}
[invocation setArgument:&nullOption
atIndex:4];
[invocation invoke];
[invocation getReturnValue:&JSON];
} else {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedString(@"Please either target a platform that supports NSJSONSerialization or add one of the following libraries to your project: JSONKit, SBJSON, or YAJL", nil)
forKey:NSLocalizedRecoverySuggestionErrorKey];
[[NSException exceptionWithName:NSInternalInconsistencyException
reason:NSLocalizedString(@"No JSON parsing functionality available", nil)
userInfo:userInfo] raise];
}
return JSON;
}
//
// LPLocation.h
// RNMonitor
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
typedef void (^RNLocatingCompletionBlock)(NSString *location, NSError *error);
@interface RNLocationManager : NSObject
@property(nonatomic,copy)NSString * location;
+ (instancetype)shareInstance;
- (void)startLocation:(RNLocatingCompletionBlock)resultBlock;
@end
//
// LPLocation.m
// RNMonitor
//
// Created by zhiyu on 17/2/22.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNLocationManager.h"
@interface RNLocationManager ()<CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager* locationManager;
@end
@implementation RNLocationManager{
RNLocatingCompletionBlock _copyresultBlock;
BOOL _hasLoction;
}
+ (instancetype)shareInstance {
static RNLocationManager *_instance;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^{
if (!_instance) {
_instance = [[self alloc] init];
}
});
return _instance;
}
- (instancetype)init
{
self = [super init];
if (self) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 1000.f;
self.locationManager.pausesLocationUpdatesAutomatically=YES;
self.locationManager.delegate = self;
}
return self;
}
- (void)startLocation:(RNLocatingCompletionBlock)resultBlock
{
_copyresultBlock = [resultBlock copy];
if ([UIDevice currentDevice].systemVersion.floatValue >=8.0) {
[_locationManager requestAlwaysAuthorization];
[_locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
CLLocation *location = [locations lastObject];
CLLocationCoordinate2D coordinate = location.coordinate;
_location = [NSString stringWithFormat:@"%f,%f",coordinate.longitude,coordinate.latitude];
[self.locationManager stopUpdatingHeading];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
_copyresultBlock(nil,error);
}
@end
//
// Created by Allen Chiang on 16/2/18.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
typedef enum {
RNMIU_CHAR, RNMIU_UNSIGNED_CHAR, RNMIU_SHORT, RNMIU_UNSIGNED_SHORT, RNMIU_INT, RNMIU_UNSIGNED, RNMIU_LONG, RNMIU_UNSIGNED_LONG,
RNMIU_LONG_LONG, RNMIU_UNSIGNED_LONG_LONG, RNMIU_DOUBLE, RNMIU_FLOAT, RNMIU_C_BOOL,
RNMIU_ID, RNMIU_STRUCT, RNMIU_FUNC, RNMIU_BLOCK, RNMIU_INT_P, RNMIU_VOID_P, RNMIU_CHAR_P, RNMIU_NIL
} RNMIU_TypeOfProperty;
@protocol RNMIUTransient
@end
@interface RNMPropertyAttributeInfo : NSObject
@property BOOL transient;
@property BOOL readOnly;
@property RNMIU_TypeOfProperty type;
@property Class clazz;
@property Class arrayClass;
@property(nonatomic, copy) NSString *dicPropertyName;
@property(nonatomic, copy) NSString *oriPropertyName;
@property SEL getter;
@property SEL setter;
@property(nonatomic, strong) NSArray *protocols;
+ (RNMPropertyAttributeInfo *)analyseProperty:(objc_property_t)pProperty
WithClass:(Class)aClass
AndWithCurrentClass:(Class)currentClass;
+ (void)enumerateClassProperties:(Class)aClass
withInfoBlock:(void (^)(Class oriClass, Class currentClass, RNMPropertyAttributeInfo *info))infoBlock;
+ (id)getValue:(id)obj with:(RNMPropertyAttributeInfo *)info;
+ (NSArray *)getProtocolsFromClass:(Class)clazz;
@end
@interface RNMPropertyAttributeInfoCache : NSObject
+ (RNMPropertyAttributeInfoCache *)instance;
- (RNMPropertyAttributeInfo *)getFromCacheWithClass:(Class)clazz AndPropertyName:(NSString *)name;
- (void)putToCacheWithClass:(Class)clazz AndPropertyName:(NSString *)name WithInfo:(RNMPropertyAttributeInfo *)info;
@end
@interface RNMIUConvertDefine :NSObject
@end
//
// Created by Allen Chiang on 16/2/18.
// Copyright (c) 2016 terminus. All rights reserved.
//
#import <objc/message.h>
#import "RNMIUConvertDefine.h"
#import <libextobjc/extobjc.h>
@implementation RNMPropertyAttributeInfoCache {
@private
NSCache *_cache;
}
- (id)init {
self = [super init];
if (self) {
_cache = [[NSCache alloc] init];
}
return self;
}
- (void)dealloc {
#if TARGET_OS_IPHONE
[[NSNotificationCenter defaultCenter] removeObserver:self];
#endif
}
+ (RNMPropertyAttributeInfoCache *)instance {
static RNMPropertyAttributeInfoCache *_instance = nil;
static dispatch_once_t _oncePredicate_PropertyAttributeInfoCache;
dispatch_once(&_oncePredicate_PropertyAttributeInfoCache, ^{
if (_instance == nil) {
_instance = [[self alloc] init];
}
}
);
return _instance;
}
- (RNMPropertyAttributeInfo *)getFromCacheWithClass:(Class)clazz
AndPropertyName:(NSString *)name {
@synchronized (self) {
NSDictionary *proInfos = [_cache objectForKey:NSStringFromClass(clazz)];
if (proInfos) {
RNMPropertyAttributeInfo *info = [proInfos objectForKey:name];
return info;
}
return nil;
}
}
- (void)putToCacheWithClass:(Class)clazz AndPropertyName:(NSString *)name
WithInfo:(RNMPropertyAttributeInfo *)info {
@synchronized (self) {
NSMutableDictionary *proInfos = [_cache objectForKey:NSStringFromClass(clazz)];
if (proInfos == nil) {
proInfos = [[NSMutableDictionary alloc] initWithCapacity:1];
[_cache setObject:proInfos
forKey:NSStringFromClass(clazz)];
}
[proInfos setObject:info
forKey:name];
}
}
- (void)clearCache {
@synchronized (self) {
[_cache removeAllObjects];
}
}
@end
@implementation RNMPropertyAttributeInfo {
@private
BOOL _transient;
BOOL _readOnly;
RNMIU_TypeOfProperty _type;
Class _clazz;
Class _arrayClass;
NSString *_dicPropertyName;
NSString *_oriPropertyName;
SEL _getter;
SEL _setter;
NSArray *_protocols;
}
@synthesize transient = _transient;
@synthesize readOnly = _readOnly;
@synthesize type = _type;
@synthesize clazz = _clazz;
@synthesize arrayClass = _arrayClass;
@synthesize dicPropertyName = _dicPropertyName;
@synthesize oriPropertyName = _oriPropertyName;
@synthesize getter = _getter;
@synthesize setter = _setter;
@synthesize protocols = _protocols;
+ (RNMPropertyAttributeInfo *)analyseProperty:(objc_property_t)pProperty
WithClass:(Class)aClass
AndWithCurrentClass:(Class)currentClass {
NSMutableString *propertyName = [NSMutableString stringWithUTF8String:property_getName(pProperty)];
RNMPropertyAttributeInfo *info;
if ((info = [[RNMPropertyAttributeInfoCache instance] getFromCacheWithClass:aClass
AndPropertyName:propertyName]) != nil) {
return info;
}
ext_propertyAttributes* pAttributes = ext_copyPropertyAttributes(pProperty);
if (NULL == pAttributes) {
return nil;
}
RNMIU_TypeOfProperty typeOfProperty = RNMIU_NIL;
Class clazz = nil;
BOOL transient = NO;
BOOL readOnly = pAttributes->readonly;
Class arrayClass = nil;
NSMutableArray *protocols = [[NSMutableArray alloc] initWithCapacity:2];
NSString *dicPropertyName = propertyName;
NSString *typeAtt = [NSString stringWithCString:pAttributes->type
encoding:NSUTF8StringEncoding];
if ([typeAtt hasPrefix:@"c"]) {
typeOfProperty = RNMIU_CHAR;
} else if ([typeAtt hasPrefix:@"C"]) {
typeOfProperty = RNMIU_UNSIGNED_CHAR;
} else if ([typeAtt hasPrefix:@"B"]) {
typeOfProperty = RNMIU_C_BOOL;
} else if ([typeAtt hasPrefix:@"d"]) {
typeOfProperty = RNMIU_DOUBLE;
} else if ([typeAtt hasPrefix:@"i"]) {
typeOfProperty = RNMIU_INT;
} else if ([typeAtt hasPrefix:@"f"]) {
typeOfProperty = RNMIU_FLOAT;
} else if ([typeAtt hasPrefix:@"l"]) {
typeOfProperty = RNMIU_LONG;
} else if ([typeAtt hasPrefix:@"L"]) {
typeOfProperty = RNMIU_UNSIGNED_LONG;
} else if ([typeAtt hasPrefix:@"q"]) {
typeOfProperty = RNMIU_LONG_LONG;
} else if ([typeAtt hasPrefix:@"Q"]) {
typeOfProperty = RNMIU_UNSIGNED_LONG_LONG;
} else if ([typeAtt hasPrefix:@"s"]) {
typeOfProperty = RNMIU_SHORT;
} else if ([typeAtt hasPrefix:@"S"]) {
typeOfProperty = RNMIU_UNSIGNED_SHORT;
} else if ([typeAtt hasPrefix:@"{"]) {
typeOfProperty = RNMIU_STRUCT;
} else if ([typeAtt hasPrefix:@"I"]) {
typeOfProperty = RNMIU_UNSIGNED;
} else if ([typeAtt hasPrefix:@"^i"]) {
typeOfProperty = RNMIU_INT_P;
} else if ([typeAtt hasPrefix:@"^v"]) {
typeOfProperty = RNMIU_VOID_P;
} else if ([typeAtt hasPrefix:@"^?"]) {
typeOfProperty = RNMIU_FUNC;
} else if ([typeAtt hasPrefix:@"*"]) {
typeOfProperty = RNMIU_CHAR_P;
} else if ([typeAtt hasPrefix:@"@"]) {
if ([typeAtt hasSuffix:[NSString stringWithCString:@encode(void (^)())
encoding:NSUTF8StringEncoding]]) {
typeOfProperty = RNMIU_BLOCK;
} else {
typeOfProperty = RNMIU_ID;
clazz = pAttributes->objectClass;
NSString *propertyType = nil;
NSString *arrayClassName;
NSString *attrStrForScan = typeAtt;
const char *const attrString = property_getAttributes(pProperty);
if (attrString) { //兼容iOS5 原来在iOS5 上NSGetSizeAndAlignment有bug 导致取出的typeAtt不对
attrStrForScan = @(attrString + 1);
}
NSScanner *scanner = [NSScanner scannerWithString:attrStrForScan];
if ([scanner scanString:@"@\""
intoString:&propertyType]) {
[scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\"<"]
intoString:&propertyType];
if (!clazz) {
clazz = NSClassFromString(propertyType);
}
while ([scanner scanString:@"<"
intoString:NULL]) {
NSString *protocolName = nil;
[scanner scanUpToString:@">"
intoString:&protocolName];
if (protocolName) {
[protocols addObject:protocolName];
}
if ([protocolName isEqualToString:NSStringFromProtocol(@protocol(RNMIUTransient))]) {
transient = YES;
} else {
arrayClassName = protocolName;
}
[scanner scanString:@">"
intoString:NULL];
}
}
if ([clazz isSubclassOfClass:[NSArray class]] || [clazz isSubclassOfClass:[NSSet class]]) {
if (arrayClassName) {
arrayClass = NSClassFromString(arrayClassName);
}
}
}
}
info = [[RNMPropertyAttributeInfo alloc] init];
info.readOnly = readOnly;
info.clazz = clazz;
info.type = typeOfProperty;
info.arrayClass = arrayClass;
info.dicPropertyName = dicPropertyName;
info.oriPropertyName = propertyName;
info.transient = [propertyName hasPrefix:@"_"] || transient;
info.setter = pAttributes->setter;
info.getter = pAttributes->getter;
info.protocols = protocols;
[[RNMPropertyAttributeInfoCache instance]
putToCacheWithClass:aClass
AndPropertyName:propertyName
WithInfo:info];
if (pAttributes != NULL) {
free(pAttributes);
}
return info;
}
+ (void)enumerateClassProperties:(Class)aClass
withInfoBlock:(void (^)(Class oriClass, Class currentClass, RNMPropertyAttributeInfo *info))infoBlock {
if (!infoBlock) {
return;
}
Class clazz = aClass;
while (clazz != nil) {
if (clazz == [NSObject class]) {
break;
}
unsigned int propertyCount;
objc_property_t *pProperty = class_copyPropertyList(clazz, &propertyCount);
if (pProperty && propertyCount > 0) {
for (unsigned int i = 0; i < propertyCount; i++) {
RNMPropertyAttributeInfo *info = [RNMPropertyAttributeInfo analyseProperty:pProperty[i]
WithClass:aClass
AndWithCurrentClass:clazz];
if (![info.oriPropertyName hasSuffix:@"ext_annotation_marker"]) {
if (class_conformsToProtocol(clazz, @protocol(NSObject)) &&
([@"hash" isEqualToString:info.oriPropertyName] ||
[@"superclass" isEqualToString:info.oriPropertyName] ||
[@"description" isEqualToString:info.oriPropertyName] ||
[@"debugDescription" isEqualToString:info.oriPropertyName])) {
continue;
}
infoBlock(aClass, clazz, info);
}
}
}
if (pProperty) {
free(pProperty);
}
clazz = class_getSuperclass(clazz);
}
}
+ (id)getValue:(id)obj with:(RNMPropertyAttributeInfo *)attributeInfo {
SEL getter = attributeInfo.getter;
id retForId = nil;
char retForChar;
unsigned char retForUnsignedChar;
bool retForBool;
double retForDouble;
int retForInt;
float retForFloat;
long retForLong;
unsigned long retForUnsignedLong;
long long retForLongLong;
unsigned long long retForUnsignedLongLong;
short retForShort;
unsigned short retForUnsignedShort;
unsigned retForUnsigned;
switch (attributeInfo.type) {
case RNMIU_CHAR:
retForChar = ((char (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithChar:retForChar];
case RNMIU_UNSIGNED_CHAR:
retForUnsignedChar = ((unsigned char (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithUnsignedChar:retForUnsignedChar];
case RNMIU_C_BOOL:
retForBool = ((bool (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithBool:retForBool];
case RNMIU_DOUBLE:
retForDouble = ((double (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithDouble:retForDouble];
case RNMIU_INT:
retForInt = ((int (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithInt:retForInt];
case RNMIU_FLOAT:
retForFloat = ((float (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithFloat:retForFloat];
case RNMIU_LONG:
retForLong = ((long (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithLong:retForLong];
case RNMIU_UNSIGNED_LONG:
retForUnsignedLong = ((unsigned long (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithUnsignedLong:retForUnsignedLong];
case RNMIU_LONG_LONG:
retForLongLong = ((long long (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithLongLong:retForLongLong];
case RNMIU_UNSIGNED_LONG_LONG:
retForUnsignedLongLong = ((unsigned long long (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithUnsignedLongLong:retForUnsignedLongLong];
case RNMIU_SHORT:
retForShort = ((short (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithShort:retForShort];
case RNMIU_UNSIGNED_SHORT:
retForUnsignedShort = ((unsigned short (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithUnsignedShort:retForUnsignedShort];
case RNMIU_UNSIGNED:
retForUnsigned = ((unsigned (*)(id, SEL)) objc_msgSend)(obj, getter);
return [NSNumber numberWithUnsignedInt:retForUnsigned];
case RNMIU_ID:
retForId = ((id (*)(id, SEL)) objc_msgSend)(obj, getter);
return retForId;
default:
break;
}
return nil;
}
+ (NSArray *)getProtocolsFromClass:(Class)clazz {
unsigned int propertyCount;
Protocol *__unsafe_unretained *pProtocol = class_copyProtocolList(clazz, &propertyCount);
NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:propertyCount];
if (pProtocol && propertyCount > 0) {
for (unsigned int i = 0; i < propertyCount; i++) {
[result addObject:NSStringFromProtocol(pProtocol[i])];
}
}
if (pProtocol) {
free(pProtocol);
}
return result;
}
@end
@implementation RNMIUConvertDefine
@end
//
// RNUtil.h
// RNMonitor
//
// Created by zhiyu on 17/2/26.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface RNUtil : NSObject
+ (NSString*)getCurrentTime;
+ (NSString*)deviceId;
@end
//
// RNUtil.m
// RNMonitor
//
// Created by zhiyu on 17/2/26.
// Copyright © 2017年 Facebook. All rights reserved.
//
#import "RNUtil.h"
@implementation RNUtil
+ (NSString*)getCurrentTime {
NSDate *date = [NSDate date];
return [NSString stringWithFormat:@"%.0f",[date timeIntervalSince1970]*1000];
}
+ (NSString *)deviceId {
return [[UIDevice currentDevice] identifierForVendor].UUIDString;
}
@end
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
typedef enum : NSInteger {
NotReachable = 0,
ReachableViaWiFi,
ReachableViaWWAN
} NetworkStatus;
#pragma mark IPv6 Support
//Reachability fully support IPv6. For full details, see ReadMe.md.
extern NSString *kReachabilityChangedNotification;
@interface Reachability : NSObject
/*!
* Use to check the reachability of a given host name.
*/
+ (instancetype)reachabilityWithHostName:(NSString *)hostName;
/*!
* Use to check the reachability of a given IP address.
*/
+ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress;
/*!
* Checks whether the default route is available. Should be used by applications that do not connect to a particular host.
*/
+ (instancetype)reachabilityForInternetConnection;
#pragma mark reachabilityForLocalWiFi
//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information.
//+ (instancetype)reachabilityForLocalWiFi;
/*!
* Start listening for reachability notifications on the current run loop.
*/
- (BOOL)startNotifier;
- (void)stopNotifier;
- (NetworkStatus)currentReachabilityStatus;
/*!
* WWAN may be available, but not active until a connection has been established. WiFi may require a connection for VPN on Demand.
*/
- (BOOL)connectionRequired;
@end
/*
Copyright (C) 2016 Apple Inc. All Rights Reserved.
See LICENSE.txt for this sample’s licensing information
Abstract:
Basic demonstration of how to use the SystemConfiguration Reachablity APIs.
*/
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <CoreFoundation/CoreFoundation.h>
#import "Reachability.h"
#pragma mark IPv6 Support
//Reachability fully support IPv6. For full details, see ReadMe.md.
NSString *kReachabilityChangedNotification = @"kNetworkReachabilityChangedNotification";
#pragma mark - Supporting functions
#define kShouldPrintReachabilityFlags 1
static void PrintReachabilityFlags(SCNetworkReachabilityFlags flags, const char* comment)
{
#if kShouldPrintReachabilityFlags
NSLog(@"Reachability Flag Status: %c%c %c%c%c%c%c%c%c %s\n",
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
(flags & kSCNetworkReachabilityFlagsReachable) ? 'R' : '-',
(flags & kSCNetworkReachabilityFlagsTransientConnection) ? 't' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionRequired) ? 'c' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) ? 'C' : '-',
(flags & kSCNetworkReachabilityFlagsInterventionRequired) ? 'i' : '-',
(flags & kSCNetworkReachabilityFlagsConnectionOnDemand) ? 'D' : '-',
(flags & kSCNetworkReachabilityFlagsIsLocalAddress) ? 'l' : '-',
(flags & kSCNetworkReachabilityFlagsIsDirect) ? 'd' : '-',
comment
);
#endif
}
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
#pragma unused (target, flags)
NSCAssert(info != NULL, @"info was NULL in ReachabilityCallback");
NSCAssert([(__bridge NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback");
Reachability* noteObject = (__bridge Reachability *)info;
// Post a notification to notify the client that the network reachability changed.
[[NSNotificationCenter defaultCenter] postNotificationName: kReachabilityChangedNotification object: noteObject];
}
#pragma mark - Reachability implementation
@implementation Reachability
{
SCNetworkReachabilityRef _reachabilityRef;
}
+ (instancetype)reachabilityWithHostName:(NSString *)hostName
{
Reachability* returnValue = NULL;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [hostName UTF8String]);
if (reachability != NULL)
{
returnValue= [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityWithAddress:(const struct sockaddr *)hostAddress
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, hostAddress);
Reachability* returnValue = NULL;
if (reachability != NULL)
{
returnValue = [[self alloc] init];
if (returnValue != NULL)
{
returnValue->_reachabilityRef = reachability;
}
else {
CFRelease(reachability);
}
}
return returnValue;
}
+ (instancetype)reachabilityForInternetConnection
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
return [self reachabilityWithAddress: (const struct sockaddr *) &zeroAddress];
}
#pragma mark reachabilityForLocalWiFi
//reachabilityForLocalWiFi has been removed from the sample. See ReadMe.md for more information.
//+ (instancetype)reachabilityForLocalWiFi
#pragma mark - Start and stop notifier
- (BOOL)startNotifier
{
BOOL returnValue = NO;
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if (SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
if (SCNetworkReachabilityScheduleWithRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode))
{
returnValue = YES;
}
}
return returnValue;
}
- (void)stopNotifier
{
if (_reachabilityRef != NULL)
{
SCNetworkReachabilityUnscheduleFromRunLoop(_reachabilityRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
}
}
- (void)dealloc
{
[self stopNotifier];
if (_reachabilityRef != NULL)
{
CFRelease(_reachabilityRef);
}
}
#pragma mark - Network Flag Handling
- (NetworkStatus)networkStatusForFlags:(SCNetworkReachabilityFlags)flags
{
PrintReachabilityFlags(flags, "networkStatusForFlags");
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// The target host is not reachable.
return NotReachable;
}
NetworkStatus returnValue = NotReachable;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
/*
If the target host is reachable and no connection is required then we'll assume (for now) that you're on Wi-Fi...
*/
returnValue = ReachableViaWiFi;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
/*
... and the connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs...
*/
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
/*
... and no [user] intervention is needed...
*/
returnValue = ReachableViaWiFi;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
/*
... but WWAN connections are OK if the calling application is using the CFNetwork APIs.
*/
returnValue = ReachableViaWWAN;
}
return returnValue;
}
- (BOOL)connectionRequired
{
NSAssert(_reachabilityRef != NULL, @"connectionRequired called with NULL reachabilityRef");
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
return (flags & kSCNetworkReachabilityFlagsConnectionRequired);
}
return NO;
}
- (NetworkStatus)currentReachabilityStatus
{
NSAssert(_reachabilityRef != NULL, @"currentNetworkStatus called with NULL SCNetworkReachabilityRef");
NetworkStatus returnValue = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(_reachabilityRef, &flags))
{
returnValue = [self networkStatusForFlags:flags];
}
return returnValue;
}
@end
require 'json'
package = JSON.parse(File.read(File.join(__dir__, '../package.json')))
Pod::Spec.new do |s|
s.name = "react-native-monitor"
s.version = "2.1.0"
s.summary = package['description']
s.description = <<-DESC
React Native apps are built using the React JS
framework, and render directly to native UIKit
elements using a fully asynchronous architecture.
There is no browser and no HTML. We have picked what
we think is the best set of features from these and
other technologies to build what we hope to become
the best product development framework available,
with an emphasis on iteration speed, developer
delight, continuity of technology, and absolutely
beautiful and fast products with no compromises in
quality or capability.
DESC
s.homepage = "http://git.terminus.io/reactnative/RNMonitor"
s.summary = "xxxxx"
s.license = package['license']
s.author = "Jianglei"
s.source = { :git => "git@git.terminus.io:reactnative/RNMonitor.git"}
s.requires_arc = true
s.platform = :ios, "7.0"
s.preserve_paths = "*.framework"
s.source_files = 'clazz/**/*.{h,m}'
s.dependency 'FMDB', '~>2.6.2'
s.dependency 'libextobjc'
end
{
"name": "react-native-monitor",
"version": "1.0.0",
"description": "## Getting started",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "http://gitlab.shop.hisense.com/wangduo3/react-native-monitor.git"
},
"author": "",
"license": "ISC"
}
# react-native-monitor
## Getting started
`$ npm install react-native-monitor --save`
### Mostly automatic installation
`$ react-native link react-native-monitor`
### Manual installation
#### iOS
1. In XCode, in the project navigator, right click `Libraries``Add Files to [your project's name]`
2. Go to `node_modules``react-native-monitor` and add `RNMonitor.xcodeproj`
3. In XCode, in the project navigator, select your project. Add `libRNMonitor.a` to your project's `Build Phases``Link Binary With Libraries`
4. Run your project (`Cmd+R`)<
#### Android
1. Open up `android/app/src/main/java/[...]/MainActivity.java`
- Add `import io.terminus.monitor.RNMonitorPackage;` to the imports at the top of the file
- Add `new RNMonitorPackage()` to the list returned by the `getPackages()` method
2. Append the following lines to `android/settings.gradle`:
```
include ':react-native-monitor'
project(':react-native-monitor').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-monitor/android')
```
3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
```
compile project(':react-native-monitor')
```
#### Windows
[Read it! :D](https://github.com/ReactWindows/react-native)
1. In Visual Studio add the `RNMonitor.sln` in `node_modules/react-native-monitor/windows/RNMonitor.sln` folder to their solution, reference from their app.
2. Open up your `MainPage.cs` app
- Add `using Cl.Json.RNMonitor;` to the usings at the top of the file
- Add `new RNMonitorPackage()` to the `List<IReactPackage>` returned by the `Packages` method
## Usage
```javascript
import RNMonitor from 'react-native-monitor';
// TODO: What do with the module?
RNMonitor;
```
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment