├── .babelrc ├── .buckconfig ├── .flowconfig ├── .gitattributes ├── .gitignore ├── .watchmanconfig ├── MSRExample ├── .buckconfig ├── .flowconfig ├── .gitignore ├── .watchmanconfig ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── msrexample │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── keystores │ │ ├── BUCK │ │ └── debug.keystore.properties │ └── settings.gradle ├── index.android.js ├── index.ios.js ├── ios │ ├── MSRExample.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── MSRExample.xcscheme │ ├── MSRExample │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── MSRExampleTests │ │ ├── Info.plist │ │ └── MSRExampleTests.m ├── package.json └── style.js ├── README.md ├── android ├── build.gradle ├── libs │ └── UniMag_SDK_v5.0.jar └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── oncethere │ └── idtechmsraudio │ ├── AutoConfigProfile.java │ ├── IDTechMSRAudioModule.java │ ├── IDTechMSRAudioPackage.java │ ├── UmReader.java │ └── UmRet.java ├── index.js ├── ios ├── IDTECH_MSR_audio.xcodeproj │ └── project.pbxproj ├── IDTECH_MSR_audio │ ├── IdTechUniMag.h │ ├── IdTechUniMag.m │ ├── utils.h │ └── utils.m └── uniMag-SDK │ ├── IDTECH_UniMag.a │ ├── UMCardData.h │ ├── UMCardData.m │ ├── uniMag.h │ └── version.txt └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | -------------------------------------------------------------------------------- /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | # We fork some components by platform. 4 | .*/*[.]android.js 5 | 6 | # Ignore templates with `@flow` in header 7 | .*/local-cli/generator.* 8 | 9 | # Ignore malformed json 10 | .*/node_modules/y18n/test/.*\.json 11 | 12 | # Ignore the website subdir 13 | /website/.* 14 | 15 | # Ignore BUCK generated dirs 16 | /\.buckd/ 17 | 18 | # Ignore unexpected extra @providesModule 19 | .*/node_modules/commoner/test/source/widget/share.js 20 | 21 | # Ignore duplicate module providers 22 | # For RN Apps installed via npm, "Libraries" folder is inside node_modules/react-native but in the source repo it is in the root 23 | .*/Libraries/react-native/React.js 24 | .*/Libraries/react-native/ReactNative.js 25 | .*/node_modules/jest-runtime/build/__tests__/.* 26 | 27 | [include] 28 | 29 | [libs] 30 | node_modules/react-native/Libraries/react-native/react-native-interface.js 31 | node_modules/react-native/flow 32 | flow/ 33 | 34 | [options] 35 | module.system=haste 36 | 37 | esproposal.class_static_fields=enable 38 | esproposal.class_instance_fields=enable 39 | 40 | experimental.strict_type_args=true 41 | 42 | munge_underscores=true 43 | 44 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 45 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 46 | 47 | suppress_type=$FlowIssue 48 | suppress_type=$FlowFixMe 49 | suppress_type=$FixMe 50 | 51 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-2]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 52 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-2]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 53 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 54 | 55 | unsafe.enable_getters_and_setters=true 56 | 57 | [version] 58 | ^0.32.0 59 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | *.iml 28 | .idea 29 | .gradle 30 | local.properties 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | 37 | # BUCK 38 | buck-out/ 39 | \.buckd/ 40 | android/app/libs 41 | android/keystores/debug.keystore 42 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /MSRExample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /MSRExample/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | # We fork some components by platform. 4 | .*/*[.]android.js 5 | 6 | # Ignore templates with `@flow` in header 7 | .*/local-cli/generator.* 8 | 9 | # Ignore malformed json 10 | .*/node_modules/y18n/test/.*\.json 11 | 12 | # Ignore the website subdir 13 | /website/.* 14 | 15 | # Ignore BUCK generated dirs 16 | /\.buckd/ 17 | 18 | # Ignore unexpected extra @providesModule 19 | .*/node_modules/commoner/test/source/widget/share.js 20 | 21 | # Ignore duplicate module providers 22 | # For RN Apps installed via npm, "Libraries" folder is inside node_modules/react-native but in the source repo it is in the root 23 | .*/Libraries/react-native/React.js 24 | .*/Libraries/react-native/ReactNative.js 25 | .*/node_modules/jest-runtime/build/__tests__/.* 26 | 27 | [include] 28 | 29 | [libs] 30 | node_modules/react-native/Libraries/react-native/react-native-interface.js 31 | node_modules/react-native/flow 32 | flow/ 33 | 34 | [options] 35 | module.system=haste 36 | 37 | esproposal.class_static_fields=enable 38 | esproposal.class_instance_fields=enable 39 | 40 | experimental.strict_type_args=true 41 | 42 | munge_underscores=true 43 | 44 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub' 45 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 46 | 47 | suppress_type=$FlowIssue 48 | suppress_type=$FlowFixMe 49 | suppress_type=$FixMe 50 | 51 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-2]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 52 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-2]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 53 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 54 | 55 | unsafe.enable_getters_and_setters=true 56 | 57 | [version] 58 | ^0.32.0 59 | -------------------------------------------------------------------------------- /MSRExample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | *.iml 28 | .idea 29 | .gradle 30 | local.properties 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | 37 | # BUCK 38 | buck-out/ 39 | \.buckd/ 40 | android/app/libs 41 | android/keystores/debug.keystore 42 | -------------------------------------------------------------------------------- /MSRExample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /MSRExample/android/app/BUCK: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | # To learn about Buck see [Docs](https://buckbuild.com/). 4 | # To run your application with Buck: 5 | # - install Buck 6 | # - `npm start` - to start the packager 7 | # - `cd android` 8 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 9 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 10 | # - `buck install -r android/app` - compile, install and run application 11 | # 12 | 13 | lib_deps = [] 14 | for jarfile in glob(['libs/*.jar']): 15 | name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile) 16 | lib_deps.append(':' + name) 17 | prebuilt_jar( 18 | name = name, 19 | binary_jar = jarfile, 20 | ) 21 | 22 | for aarfile in glob(['libs/*.aar']): 23 | name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile) 24 | lib_deps.append(':' + name) 25 | android_prebuilt_aar( 26 | name = name, 27 | aar = aarfile, 28 | ) 29 | 30 | android_library( 31 | name = 'all-libs', 32 | exported_deps = lib_deps 33 | ) 34 | 35 | android_library( 36 | name = 'app-code', 37 | srcs = glob([ 38 | 'src/main/java/**/*.java', 39 | ]), 40 | deps = [ 41 | ':all-libs', 42 | ':build_config', 43 | ':res', 44 | ], 45 | ) 46 | 47 | android_build_config( 48 | name = 'build_config', 49 | package = 'com.msrexample', 50 | ) 51 | 52 | android_resource( 53 | name = 'res', 54 | res = 'src/main/res', 55 | package = 'com.msrexample', 56 | ) 57 | 58 | android_binary( 59 | name = 'app', 60 | package_type = 'debug', 61 | manifest = 'src/main/AndroidManifest.xml', 62 | keystore = '//android/keystores:debug', 63 | deps = [ 64 | ':app-code', 65 | ], 66 | ) 67 | -------------------------------------------------------------------------------- /MSRExample/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | import com.android.build.OutputFile 4 | 5 | /** 6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 7 | * and bundleReleaseJsAndAssets). 8 | * These basically call `react-native bundle` with the correct arguments during the Android build 9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 10 | * bundle directly from the development server. Below you can see all the possible configurations 11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 12 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 13 | * 14 | * project.ext.react = [ 15 | * // the name of the generated asset file containing your JS bundle 16 | * bundleAssetName: "index.android.bundle", 17 | * 18 | * // the entry file for bundle generation 19 | * entryFile: "index.android.js", 20 | * 21 | * // whether to bundle JS and assets in debug mode 22 | * bundleInDebug: false, 23 | * 24 | * // whether to bundle JS and assets in release mode 25 | * bundleInRelease: true, 26 | * 27 | * // whether to bundle JS and assets in another build variant (if configured). 28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 29 | * // The configuration property can be in the following formats 30 | * // 'bundleIn${productFlavor}${buildType}' 31 | * // 'bundleIn${buildType}' 32 | * // bundleInFreeDebug: true, 33 | * // bundleInPaidRelease: true, 34 | * // bundleInBeta: true, 35 | * 36 | * // the root of your project, i.e. where "package.json" lives 37 | * root: "../../", 38 | * 39 | * // where to put the JS bundle asset in debug mode 40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 41 | * 42 | * // where to put the JS bundle asset in release mode 43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 44 | * 45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 46 | * // require('./image.png')), in debug mode 47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 48 | * 49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 50 | * // require('./image.png')), in release mode 51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 52 | * 53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 57 | * // for example, you might want to remove it from here. 58 | * inputExcludes: ["android/**", "ios/**"], 59 | * 60 | * // override which node gets called and with what additional arguments 61 | * nodeExecutableAndArgs: ["node"] 62 | * 63 | * // supply additional arguments to the packager 64 | * extraPackagerArgs: [] 65 | * ] 66 | */ 67 | 68 | apply from: "../../node_modules/react-native/react.gradle" 69 | 70 | /** 71 | * Set this to true to create two separate APKs instead of one: 72 | * - An APK that only works on ARM devices 73 | * - An APK that only works on x86 devices 74 | * The advantage is the size of the APK is reduced by about 4MB. 75 | * Upload all the APKs to the Play Store and people will download 76 | * the correct one based on the CPU architecture of their device. 77 | */ 78 | def enableSeparateBuildPerCPUArchitecture = false 79 | 80 | /** 81 | * Run Proguard to shrink the Java bytecode in release builds. 82 | */ 83 | def enableProguardInReleaseBuilds = false 84 | 85 | android { 86 | compileSdkVersion 23 87 | buildToolsVersion "23.0.1" 88 | 89 | defaultConfig { 90 | applicationId "com.msrexample" 91 | minSdkVersion 16 92 | targetSdkVersion 22 93 | versionCode 1 94 | versionName "1.0" 95 | ndk { 96 | abiFilters "armeabi-v7a", "x86" 97 | } 98 | } 99 | splits { 100 | abi { 101 | reset() 102 | enable enableSeparateBuildPerCPUArchitecture 103 | universalApk false // If true, also generate a universal APK 104 | include "armeabi-v7a", "x86" 105 | } 106 | } 107 | buildTypes { 108 | release { 109 | minifyEnabled enableProguardInReleaseBuilds 110 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 111 | } 112 | } 113 | // applicationVariants are e.g. debug, release 114 | applicationVariants.all { variant -> 115 | variant.outputs.each { output -> 116 | // For each separate APK per architecture, set a unique version code as described here: 117 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits 118 | def versionCodes = ["armeabi-v7a":1, "x86":2] 119 | def abi = output.getFilter(OutputFile.ABI) 120 | if (abi != null) { // null for the universal-debug, universal-release variants 121 | output.versionCodeOverride = 122 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 123 | } 124 | } 125 | } 126 | } 127 | 128 | dependencies { 129 | compile fileTree(dir: "libs", include: ["*.jar"]) 130 | compile "com.android.support:appcompat-v7:23.0.1" 131 | compile "com.facebook.react:react-native:+" // From node_modules 132 | } 133 | 134 | // Run this once to be able to run the application with BUCK 135 | // puts all compile dependencies into folder libs for BUCK to use 136 | task copyDownloadableDepsToLibs(type: Copy) { 137 | from configurations.compile 138 | into 'libs' 139 | } 140 | -------------------------------------------------------------------------------- /MSRExample/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Disabling obfuscation is useful if you collect stack traces from production crashes 20 | # (unless you are using a system that supports de-obfuscate the stack traces). 21 | -dontobfuscate 22 | 23 | # React Native 24 | 25 | # Keep our interfaces so they can be used by other ProGuard rules. 26 | # See http://sourceforge.net/p/proguard/bugs/466/ 27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip 28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters 29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip 30 | 31 | # Do not strip any method/class that is annotated with @DoNotStrip 32 | -keep @com.facebook.proguard.annotations.DoNotStrip class * 33 | -keep @com.facebook.common.internal.DoNotStrip class * 34 | -keepclassmembers class * { 35 | @com.facebook.proguard.annotations.DoNotStrip *; 36 | @com.facebook.common.internal.DoNotStrip *; 37 | } 38 | 39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { 40 | void set*(***); 41 | *** get*(); 42 | } 43 | 44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } 45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; } 46 | -keepclassmembers,includedescriptorclasses class * { native ; } 47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } 48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } 49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } 50 | 51 | -dontwarn com.facebook.react.** 52 | 53 | # okhttp 54 | 55 | -keepattributes Signature 56 | -keepattributes *Annotation* 57 | -keep class okhttp3.** { *; } 58 | -keep interface okhttp3.** { *; } 59 | -dontwarn okhttp3.** 60 | 61 | # okio 62 | 63 | -keep class sun.misc.Unsafe { *; } 64 | -dontwarn java.nio.file.* 65 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement 66 | -dontwarn okio.** 67 | -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/java/com/msrexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.msrexample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. 9 | * This is used to schedule rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "MSRExample"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/java/com/msrexample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.msrexample; 2 | 3 | import android.app.Application; 4 | import android.util.Log; 5 | 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.react.shell.MainReactPackage; 11 | 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class MainApplication extends Application implements ReactApplication { 16 | 17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 18 | @Override 19 | protected boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | return Arrays.asList( 26 | new MainReactPackage() 27 | ); 28 | } 29 | }; 30 | 31 | @Override 32 | public ReactNativeHost getReactNativeHost() { 33 | return mReactNativeHost; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/MSRExample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/MSRExample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/MSRExample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/MSRExample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | MSRExample 3 | 4 | -------------------------------------------------------------------------------- /MSRExample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MSRExample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$rootDir/../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /MSRExample/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /MSRExample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/MSRExample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /MSRExample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 6 | -------------------------------------------------------------------------------- /MSRExample/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /MSRExample/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /MSRExample/android/keystores/BUCK: -------------------------------------------------------------------------------- 1 | keystore( 2 | name = 'debug', 3 | store = 'debug.keystore', 4 | properties = 'debug.keystore.properties', 5 | visibility = [ 6 | 'PUBLIC', 7 | ], 8 | ) 9 | -------------------------------------------------------------------------------- /MSRExample/android/keystores/debug.keystore.properties: -------------------------------------------------------------------------------- 1 | key.store=debug.keystore 2 | key.alias=androiddebugkey 3 | key.store.password=android 4 | key.alias.password=android 5 | -------------------------------------------------------------------------------- /MSRExample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'MSRExample' 2 | 3 | include ':app' 4 | -------------------------------------------------------------------------------- /MSRExample/index.android.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Example React Native App using react-native-idtech-msr-audio 3 | * 4 | * ToDo: implement Android native code for ID Tech reader 5 | */ 6 | 7 | import React, { Component } from 'react'; 8 | import { 9 | AppRegistry, 10 | StyleSheet, 11 | Text, 12 | View, 13 | TouchableHighlight, 14 | NativeModules, NativeEventEmitter, 15 | } from 'react-native'; 16 | import styles from './style'; 17 | 18 | import IDTECH_MSR_audio from 'react-native-idtech-msr-audio'; 19 | 20 | class MSRExample extends Component { 21 | 22 | constructor(props) { 23 | super(props); 24 | 25 | this.state = { 26 | details: [], 27 | connected: false, 28 | connecting: false, 29 | }; 30 | } 31 | 32 | componentWillMount() { 33 | // Listen for events from the card reader. 34 | const IdTechUniMagEvent = new NativeEventEmitter(NativeModules.IDTECH_MSR_audio); 35 | this.IdTechUniMagEventSub = IdTechUniMagEvent.addListener( 36 | 'IdTechUniMagEvent', 37 | (response) => { 38 | let texts = [response.type, response.message] 39 | let details = []; 40 | for (let i=0; i 43 | {texts[i]} 44 | 45 | ); 46 | } 47 | if (response.type === 'umSwipe_receivedSwipe') { 48 | console.log("Successfully received swipe."); 49 | // ToDo: Display card data 50 | } 51 | this.setState({details}); 52 | } 53 | ); 54 | } 55 | 56 | componentWillUnmount() { 57 | this.IdTechUniMagEventSub.remove(); 58 | } 59 | 60 | connectReader() { 61 | // Initiate a transaction on the card reader. 62 | this.setState({connecting: true}); 63 | // Params: 4 = Shuttle, 0 timeout (infinite), no logging 64 | IDTECH_MSR_audio.activate(4, 0, false).then( 65 | (response) =>{ 66 | let connecting = false; 67 | let connected = response.statusCode === 0; 68 | let details = ( 69 | 70 | {response.message} 71 | 72 | ) 73 | this.setState({connecting, connected, details}); 74 | 75 | // console.log("IDTECH_MSR_audio activation response:" + JSON.stringify(response)); 76 | }); 77 | } 78 | 79 | disconnectReader() { 80 | IDTECH_MSR_audio.deactivate(); 81 | this.setState({connecting: false, connected: false}); 82 | } 83 | 84 | startSwipe() { 85 | IDTECH_MSR_audio.swipe(); 86 | } 87 | 88 | 89 | render() { 90 | let buttonStyle = this.state.connecting? styles.buttonDisabled : null; 91 | return ( 92 | 93 | 94 | ID TECH MagStripe Reader (audio jack) 95 | React Native Integration Demo 96 | 97 | 98 | {this.state.details} 99 | 100 | 101 | this.state.connected ? this.disconnectReader() : this.connectReader()} 105 | underlayColor="#f1f1f1"> 106 | {this.state.connected ? 'Disconnect' : 'Connect'} 107 | 108 | 109 | { this.state.connected && 110 | 114 | Start Swipe 115 | 116 | } 117 | 118 | ); 119 | } 120 | } 121 | 122 | AppRegistry.registerComponent('MSRExample', () => MSRExample); 123 | -------------------------------------------------------------------------------- /MSRExample/index.ios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Example React Native App using react-native-idtech-msr-audio 3 | */ 4 | 5 | import React, { Component } from 'react'; 6 | import { 7 | AppRegistry, 8 | StyleSheet, 9 | Text, 10 | View, 11 | TouchableHighlight, 12 | NativeModules, NativeEventEmitter, 13 | } from 'react-native'; 14 | import styles from './style'; 15 | 16 | import IDTECH_MSR_audio from 'react-native-idtech-msr-audio'; 17 | 18 | class MSRExample extends Component { 19 | 20 | constructor(props) { 21 | super(props); 22 | 23 | this.state = { 24 | details: [], 25 | connected: false, 26 | connecting: false, 27 | swiping: false, 28 | }; 29 | 30 | this.startSwipe = this.startSwipe.bind(this); 31 | } 32 | 33 | componentWillMount() { 34 | // Listen for events from the card reader. 35 | const IdTechUniMagEvent = new NativeEventEmitter(NativeModules.IDTECH_MSR_audio); 36 | this.IdTechUniMagEventSub = IdTechUniMagEvent.addListener( 37 | 'IdTechUniMagEvent', 38 | (response) => { 39 | let swiping = this.state.swiping; 40 | let connected = this.state.connected; 41 | let texts = [response.type, response.message] 42 | 43 | if (response.type === 'umConnection_connected') { 44 | connected = true; 45 | } 46 | 47 | let details = []; 48 | for (let i=0; i 51 | {texts[i]} 52 | 53 | ); 54 | } 55 | if (response.type === 'umSwipe_receivedSwipe') { 56 | swiping = false; 57 | for (let i=0; i 60 | Track {i+1}: {response.data.tracks[i]} 61 | 62 | ); 63 | } 64 | } 65 | this.setState({details, connected, swiping}); 66 | } 67 | ); 68 | } 69 | 70 | componentWillUnmount() { 71 | this.IdTechUniMagEventSub.remove(); 72 | } 73 | 74 | connectReader() { 75 | // Initiate a transaction on the card reader. 76 | this.setState({connecting: true}); 77 | // Params: 4 = Shuttle, 0 = infinite timeout, false = no logging 78 | IDTECH_MSR_audio.activate(4, 0, false).then( 79 | (response) =>{ 80 | let connecting = false; 81 | let details = ( 82 | 83 | {response.message} 84 | 85 | ) 86 | this.setState({connecting, details}); 87 | 88 | // console.log("IDTECH_MSR_audio activation response:" + JSON.stringify(response)); 89 | }); 90 | } 91 | 92 | disconnectReader() { 93 | IDTECH_MSR_audio.deactivate(); 94 | this.setState({connecting: false, connected: false, swiping: false, details: []}); 95 | } 96 | 97 | startSwipe() { 98 | IDTECH_MSR_audio.swipe(); 99 | this.setState({swiping: true}); 100 | } 101 | 102 | 103 | render() { 104 | let buttonStyle = this.state.connecting? styles.buttonDisabled : null; 105 | return ( 106 | 107 | 108 | ID TECH MagStripe Reader (audio jack) 109 | React Native Integration Demo 110 | 111 | 112 | {this.state.details} 113 | 114 | 115 | this.state.connected ? this.disconnectReader() : this.connectReader()} 119 | underlayColor="#f1f1f1"> 120 | {this.state.connected ? 'Disconnect' : 'Connect'} 121 | 122 | 123 | { this.state.connected && !this.state.swiping && 124 | 128 | Start Swipe 129 | 130 | } 131 | 132 | ); 133 | } 134 | } 135 | 136 | AppRegistry.registerComponent('MSRExample', () => MSRExample); 137 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 11 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 12 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 13 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 14 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 15 | 00E356F31AD99517003FC87E /* MSRExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* MSRExampleTests.m */; }; 16 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 17 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 18 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; 19 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 20 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 21 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 22 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 23 | 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 24 | 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 25 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 26 | CEDAE12C1EE0794300D3C184 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEDAE12B1EE0794300D3C184 /* MediaPlayer.framework */; }; 27 | CEDAE12E1EE0794800D3C184 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEDAE12D1EE0794800D3C184 /* AudioToolbox.framework */; }; 28 | CEDAE1301EE0795D00D3C184 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEDAE12F1EE0795D00D3C184 /* AVFoundation.framework */; }; 29 | EF7BA49B17EC4200B807E308 /* libIDTECH_MSR_audio.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA742F3A4B348D79D1B9C32 /* libIDTECH_MSR_audio.a */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 36 | proxyType = 2; 37 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 38 | remoteInfo = RCTActionSheet; 39 | }; 40 | 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 43 | proxyType = 2; 44 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 45 | remoteInfo = RCTGeolocation; 46 | }; 47 | 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 50 | proxyType = 2; 51 | remoteGlobalIDString = 58B5115D1A9E6B3D00147676; 52 | remoteInfo = RCTImage; 53 | }; 54 | 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 57 | proxyType = 2; 58 | remoteGlobalIDString = 58B511DB1A9E6C8500147676; 59 | remoteInfo = RCTNetwork; 60 | }; 61 | 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { 62 | isa = PBXContainerItemProxy; 63 | containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 64 | proxyType = 2; 65 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; 66 | remoteInfo = RCTVibration; 67 | }; 68 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { 69 | isa = PBXContainerItemProxy; 70 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; 71 | proxyType = 1; 72 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A; 73 | remoteInfo = MSRExample; 74 | }; 75 | 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { 76 | isa = PBXContainerItemProxy; 77 | containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; 78 | proxyType = 2; 79 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 80 | remoteInfo = RCTSettings; 81 | }; 82 | 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { 83 | isa = PBXContainerItemProxy; 84 | containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; 85 | proxyType = 2; 86 | remoteGlobalIDString = 3C86DF461ADF2C930047B81A; 87 | remoteInfo = RCTWebSocket; 88 | }; 89 | 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { 90 | isa = PBXContainerItemProxy; 91 | containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; 92 | proxyType = 2; 93 | remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; 94 | remoteInfo = React; 95 | }; 96 | 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { 97 | isa = PBXContainerItemProxy; 98 | containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; 99 | proxyType = 2; 100 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 101 | remoteInfo = RCTLinking; 102 | }; 103 | 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { 104 | isa = PBXContainerItemProxy; 105 | containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 106 | proxyType = 2; 107 | remoteGlobalIDString = 58B5119B1A9E6C1200147676; 108 | remoteInfo = RCTText; 109 | }; 110 | CE3F88EE1EF860D300620913 /* PBXContainerItemProxy */ = { 111 | isa = PBXContainerItemProxy; 112 | containerPortal = DA2B7F7320E441A5B4AE44A4 /* IDTECH_MSR_audio.xcodeproj */; 113 | proxyType = 2; 114 | remoteGlobalIDString = CEAD77581EDF23B000FE9280; 115 | remoteInfo = IDTECH_MSR_audio; 116 | }; 117 | /* End PBXContainerItemProxy section */ 118 | 119 | /* Begin PBXFileReference section */ 120 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; 121 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; 122 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; 123 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 124 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 125 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; 126 | 00E356EE1AD99517003FC87E /* MSRExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MSRExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 127 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 128 | 00E356F21AD99517003FC87E /* MSRExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSRExampleTests.m; sourceTree = ""; }; 129 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 130 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; 131 | 13B07F961A680F5B00A75B9A /* MSRExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MSRExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 132 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = MSRExample/AppDelegate.h; sourceTree = ""; }; 133 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = MSRExample/AppDelegate.m; sourceTree = ""; }; 134 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 135 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = MSRExample/Images.xcassets; sourceTree = ""; }; 136 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = MSRExample/Info.plist; sourceTree = ""; }; 137 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = MSRExample/main.m; sourceTree = ""; }; 138 | 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; 139 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; 140 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; 141 | CEDAE12B1EE0794300D3C184 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; 142 | CEDAE12D1EE0794800D3C184 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 143 | CEDAE12F1EE0795D00D3C184 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 144 | DA2B7F7320E441A5B4AE44A4 /* IDTECH_MSR_audio.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = IDTECH_MSR_audio.xcodeproj; path = "../node_modules/react-native-idtech-msr-audio/ios/IDTECH_MSR_audio.xcodeproj"; sourceTree = ""; }; 145 | EFA742F3A4B348D79D1B9C32 /* libIDTECH_MSR_audio.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libIDTECH_MSR_audio.a; sourceTree = ""; }; 146 | /* End PBXFileReference section */ 147 | 148 | /* Begin PBXFrameworksBuildPhase section */ 149 | 00E356EB1AD99517003FC87E /* Frameworks */ = { 150 | isa = PBXFrameworksBuildPhase; 151 | buildActionMask = 2147483647; 152 | files = ( 153 | 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 158 | isa = PBXFrameworksBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | CEDAE1301EE0795D00D3C184 /* AVFoundation.framework in Frameworks */, 162 | CEDAE12E1EE0794800D3C184 /* AudioToolbox.framework in Frameworks */, 163 | CEDAE12C1EE0794300D3C184 /* MediaPlayer.framework in Frameworks */, 164 | 146834051AC3E58100842450 /* libReact.a in Frameworks */, 165 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 166 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 167 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 168 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, 169 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 170 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, 171 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 172 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 173 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, 174 | EF7BA49B17EC4200B807E308 /* libIDTECH_MSR_audio.a in Frameworks */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXFrameworksBuildPhase section */ 179 | 180 | /* Begin PBXGroup section */ 181 | 00C302A81ABCB8CE00DB3ED1 /* Products */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, 185 | ); 186 | name = Products; 187 | sourceTree = ""; 188 | }; 189 | 00C302B61ABCB90400DB3ED1 /* Products */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, 193 | ); 194 | name = Products; 195 | sourceTree = ""; 196 | }; 197 | 00C302BC1ABCB91800DB3ED1 /* Products */ = { 198 | isa = PBXGroup; 199 | children = ( 200 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 201 | ); 202 | name = Products; 203 | sourceTree = ""; 204 | }; 205 | 00C302D41ABCB9D200DB3ED1 /* Products */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 209 | ); 210 | name = Products; 211 | sourceTree = ""; 212 | }; 213 | 00C302E01ABCB9EE00DB3ED1 /* Products */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, 217 | ); 218 | name = Products; 219 | sourceTree = ""; 220 | }; 221 | 00E356EF1AD99517003FC87E /* MSRExampleTests */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 00E356F21AD99517003FC87E /* MSRExampleTests.m */, 225 | 00E356F01AD99517003FC87E /* Supporting Files */, 226 | ); 227 | path = MSRExampleTests; 228 | sourceTree = ""; 229 | }; 230 | 00E356F01AD99517003FC87E /* Supporting Files */ = { 231 | isa = PBXGroup; 232 | children = ( 233 | 00E356F11AD99517003FC87E /* Info.plist */, 234 | ); 235 | name = "Supporting Files"; 236 | sourceTree = ""; 237 | }; 238 | 139105B71AF99BAD00B5F7CC /* Products */ = { 239 | isa = PBXGroup; 240 | children = ( 241 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, 242 | ); 243 | name = Products; 244 | sourceTree = ""; 245 | }; 246 | 139FDEE71B06529A00C62182 /* Products */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, 250 | ); 251 | name = Products; 252 | sourceTree = ""; 253 | }; 254 | 13B07FAE1A68108700A75B9A /* MSRExample */ = { 255 | isa = PBXGroup; 256 | children = ( 257 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 258 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 259 | 13B07FB01A68108700A75B9A /* AppDelegate.m */, 260 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 261 | 13B07FB61A68108700A75B9A /* Info.plist */, 262 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 263 | 13B07FB71A68108700A75B9A /* main.m */, 264 | ); 265 | name = MSRExample; 266 | sourceTree = ""; 267 | }; 268 | 146834001AC3E56700842450 /* Products */ = { 269 | isa = PBXGroup; 270 | children = ( 271 | 146834041AC3E56700842450 /* libReact.a */, 272 | ); 273 | name = Products; 274 | sourceTree = ""; 275 | }; 276 | 78C398B11ACF4ADC00677621 /* Products */ = { 277 | isa = PBXGroup; 278 | children = ( 279 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, 280 | ); 281 | name = Products; 282 | sourceTree = ""; 283 | }; 284 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 285 | isa = PBXGroup; 286 | children = ( 287 | 146833FF1AC3E56700842450 /* React.xcodeproj */, 288 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, 289 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 290 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 291 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, 292 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, 293 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, 294 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 295 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 296 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, 297 | DA2B7F7320E441A5B4AE44A4 /* IDTECH_MSR_audio.xcodeproj */, 298 | ); 299 | name = Libraries; 300 | sourceTree = ""; 301 | }; 302 | 832341B11AAA6A8300B99B32 /* Products */ = { 303 | isa = PBXGroup; 304 | children = ( 305 | 832341B51AAA6A8300B99B32 /* libRCTText.a */, 306 | ); 307 | name = Products; 308 | sourceTree = ""; 309 | }; 310 | 83CBB9F61A601CBA00E9B192 = { 311 | isa = PBXGroup; 312 | children = ( 313 | 13B07FAE1A68108700A75B9A /* MSRExample */, 314 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 315 | 00E356EF1AD99517003FC87E /* MSRExampleTests */, 316 | 83CBBA001A601CBA00E9B192 /* Products */, 317 | CEDAE12A1EE0794300D3C184 /* Frameworks */, 318 | ); 319 | indentWidth = 2; 320 | sourceTree = ""; 321 | tabWidth = 2; 322 | }; 323 | 83CBBA001A601CBA00E9B192 /* Products */ = { 324 | isa = PBXGroup; 325 | children = ( 326 | 13B07F961A680F5B00A75B9A /* MSRExample.app */, 327 | 00E356EE1AD99517003FC87E /* MSRExampleTests.xctest */, 328 | ); 329 | name = Products; 330 | sourceTree = ""; 331 | }; 332 | CE3F88EB1EF860D200620913 /* Products */ = { 333 | isa = PBXGroup; 334 | children = ( 335 | CE3F88EF1EF860D300620913 /* libIDTECH_MSR_audio.a */, 336 | ); 337 | name = Products; 338 | sourceTree = ""; 339 | }; 340 | CEDAE12A1EE0794300D3C184 /* Frameworks */ = { 341 | isa = PBXGroup; 342 | children = ( 343 | CEDAE12F1EE0795D00D3C184 /* AVFoundation.framework */, 344 | CEDAE12D1EE0794800D3C184 /* AudioToolbox.framework */, 345 | CEDAE12B1EE0794300D3C184 /* MediaPlayer.framework */, 346 | ); 347 | name = Frameworks; 348 | sourceTree = ""; 349 | }; 350 | /* End PBXGroup section */ 351 | 352 | /* Begin PBXNativeTarget section */ 353 | 00E356ED1AD99517003FC87E /* MSRExampleTests */ = { 354 | isa = PBXNativeTarget; 355 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "MSRExampleTests" */; 356 | buildPhases = ( 357 | 00E356EA1AD99517003FC87E /* Sources */, 358 | 00E356EB1AD99517003FC87E /* Frameworks */, 359 | 00E356EC1AD99517003FC87E /* Resources */, 360 | ); 361 | buildRules = ( 362 | ); 363 | dependencies = ( 364 | 00E356F51AD99517003FC87E /* PBXTargetDependency */, 365 | ); 366 | name = MSRExampleTests; 367 | productName = MSRExampleTests; 368 | productReference = 00E356EE1AD99517003FC87E /* MSRExampleTests.xctest */; 369 | productType = "com.apple.product-type.bundle.unit-test"; 370 | }; 371 | 13B07F861A680F5B00A75B9A /* MSRExample */ = { 372 | isa = PBXNativeTarget; 373 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MSRExample" */; 374 | buildPhases = ( 375 | 13B07F871A680F5B00A75B9A /* Sources */, 376 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 377 | 13B07F8E1A680F5B00A75B9A /* Resources */, 378 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 379 | ); 380 | buildRules = ( 381 | ); 382 | dependencies = ( 383 | ); 384 | name = MSRExample; 385 | productName = "Hello World"; 386 | productReference = 13B07F961A680F5B00A75B9A /* MSRExample.app */; 387 | productType = "com.apple.product-type.application"; 388 | }; 389 | /* End PBXNativeTarget section */ 390 | 391 | /* Begin PBXProject section */ 392 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 393 | isa = PBXProject; 394 | attributes = { 395 | LastUpgradeCheck = 610; 396 | ORGANIZATIONNAME = Facebook; 397 | TargetAttributes = { 398 | 00E356ED1AD99517003FC87E = { 399 | CreatedOnToolsVersion = 6.2; 400 | TestTargetID = 13B07F861A680F5B00A75B9A; 401 | }; 402 | 13B07F861A680F5B00A75B9A = { 403 | DevelopmentTeam = RRS6DX4EXX; 404 | }; 405 | }; 406 | }; 407 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MSRExample" */; 408 | compatibilityVersion = "Xcode 3.2"; 409 | developmentRegion = English; 410 | hasScannedForEncodings = 0; 411 | knownRegions = ( 412 | en, 413 | Base, 414 | ); 415 | mainGroup = 83CBB9F61A601CBA00E9B192; 416 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 417 | projectDirPath = ""; 418 | projectReferences = ( 419 | { 420 | ProductGroup = CE3F88EB1EF860D200620913 /* Products */; 421 | ProjectRef = DA2B7F7320E441A5B4AE44A4 /* IDTECH_MSR_audio.xcodeproj */; 422 | }, 423 | { 424 | ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; 425 | ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 426 | }, 427 | { 428 | ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; 429 | ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 430 | }, 431 | { 432 | ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; 433 | ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 434 | }, 435 | { 436 | ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; 437 | ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; 438 | }, 439 | { 440 | ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; 441 | ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 442 | }, 443 | { 444 | ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; 445 | ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; 446 | }, 447 | { 448 | ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; 449 | ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 450 | }, 451 | { 452 | ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; 453 | ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 454 | }, 455 | { 456 | ProductGroup = 139FDEE71B06529A00C62182 /* Products */; 457 | ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; 458 | }, 459 | { 460 | ProductGroup = 146834001AC3E56700842450 /* Products */; 461 | ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; 462 | }, 463 | ); 464 | projectRoot = ""; 465 | targets = ( 466 | 13B07F861A680F5B00A75B9A /* MSRExample */, 467 | 00E356ED1AD99517003FC87E /* MSRExampleTests */, 468 | ); 469 | }; 470 | /* End PBXProject section */ 471 | 472 | /* Begin PBXReferenceProxy section */ 473 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { 474 | isa = PBXReferenceProxy; 475 | fileType = archive.ar; 476 | path = libRCTActionSheet.a; 477 | remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; 478 | sourceTree = BUILT_PRODUCTS_DIR; 479 | }; 480 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { 481 | isa = PBXReferenceProxy; 482 | fileType = archive.ar; 483 | path = libRCTGeolocation.a; 484 | remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; 485 | sourceTree = BUILT_PRODUCTS_DIR; 486 | }; 487 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { 488 | isa = PBXReferenceProxy; 489 | fileType = archive.ar; 490 | path = libRCTImage.a; 491 | remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; 492 | sourceTree = BUILT_PRODUCTS_DIR; 493 | }; 494 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { 495 | isa = PBXReferenceProxy; 496 | fileType = archive.ar; 497 | path = libRCTNetwork.a; 498 | remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; 499 | sourceTree = BUILT_PRODUCTS_DIR; 500 | }; 501 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { 502 | isa = PBXReferenceProxy; 503 | fileType = archive.ar; 504 | path = libRCTVibration.a; 505 | remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; 506 | sourceTree = BUILT_PRODUCTS_DIR; 507 | }; 508 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { 509 | isa = PBXReferenceProxy; 510 | fileType = archive.ar; 511 | path = libRCTSettings.a; 512 | remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; 513 | sourceTree = BUILT_PRODUCTS_DIR; 514 | }; 515 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { 516 | isa = PBXReferenceProxy; 517 | fileType = archive.ar; 518 | path = libRCTWebSocket.a; 519 | remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; 520 | sourceTree = BUILT_PRODUCTS_DIR; 521 | }; 522 | 146834041AC3E56700842450 /* libReact.a */ = { 523 | isa = PBXReferenceProxy; 524 | fileType = archive.ar; 525 | path = libReact.a; 526 | remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; 527 | sourceTree = BUILT_PRODUCTS_DIR; 528 | }; 529 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { 530 | isa = PBXReferenceProxy; 531 | fileType = archive.ar; 532 | path = libRCTLinking.a; 533 | remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; 534 | sourceTree = BUILT_PRODUCTS_DIR; 535 | }; 536 | 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { 537 | isa = PBXReferenceProxy; 538 | fileType = archive.ar; 539 | path = libRCTText.a; 540 | remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; 541 | sourceTree = BUILT_PRODUCTS_DIR; 542 | }; 543 | CE3F88EF1EF860D300620913 /* libIDTECH_MSR_audio.a */ = { 544 | isa = PBXReferenceProxy; 545 | fileType = archive.ar; 546 | path = libIDTECH_MSR_audio.a; 547 | remoteRef = CE3F88EE1EF860D300620913 /* PBXContainerItemProxy */; 548 | sourceTree = BUILT_PRODUCTS_DIR; 549 | }; 550 | /* End PBXReferenceProxy section */ 551 | 552 | /* Begin PBXResourcesBuildPhase section */ 553 | 00E356EC1AD99517003FC87E /* Resources */ = { 554 | isa = PBXResourcesBuildPhase; 555 | buildActionMask = 2147483647; 556 | files = ( 557 | ); 558 | runOnlyForDeploymentPostprocessing = 0; 559 | }; 560 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 561 | isa = PBXResourcesBuildPhase; 562 | buildActionMask = 2147483647; 563 | files = ( 564 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 565 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 566 | ); 567 | runOnlyForDeploymentPostprocessing = 0; 568 | }; 569 | /* End PBXResourcesBuildPhase section */ 570 | 571 | /* Begin PBXShellScriptBuildPhase section */ 572 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { 573 | isa = PBXShellScriptBuildPhase; 574 | buildActionMask = 2147483647; 575 | files = ( 576 | ); 577 | inputPaths = ( 578 | ); 579 | name = "Bundle React Native code and images"; 580 | outputPaths = ( 581 | ); 582 | runOnlyForDeploymentPostprocessing = 0; 583 | shellPath = /bin/sh; 584 | shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh"; 585 | }; 586 | /* End PBXShellScriptBuildPhase section */ 587 | 588 | /* Begin PBXSourcesBuildPhase section */ 589 | 00E356EA1AD99517003FC87E /* Sources */ = { 590 | isa = PBXSourcesBuildPhase; 591 | buildActionMask = 2147483647; 592 | files = ( 593 | 00E356F31AD99517003FC87E /* MSRExampleTests.m in Sources */, 594 | ); 595 | runOnlyForDeploymentPostprocessing = 0; 596 | }; 597 | 13B07F871A680F5B00A75B9A /* Sources */ = { 598 | isa = PBXSourcesBuildPhase; 599 | buildActionMask = 2147483647; 600 | files = ( 601 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 602 | 13B07FC11A68108700A75B9A /* main.m in Sources */, 603 | ); 604 | runOnlyForDeploymentPostprocessing = 0; 605 | }; 606 | /* End PBXSourcesBuildPhase section */ 607 | 608 | /* Begin PBXTargetDependency section */ 609 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { 610 | isa = PBXTargetDependency; 611 | target = 13B07F861A680F5B00A75B9A /* MSRExample */; 612 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; 613 | }; 614 | /* End PBXTargetDependency section */ 615 | 616 | /* Begin PBXVariantGroup section */ 617 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { 618 | isa = PBXVariantGroup; 619 | children = ( 620 | 13B07FB21A68108700A75B9A /* Base */, 621 | ); 622 | name = LaunchScreen.xib; 623 | path = MSRExample; 624 | sourceTree = ""; 625 | }; 626 | /* End PBXVariantGroup section */ 627 | 628 | /* Begin XCBuildConfiguration section */ 629 | 00E356F61AD99517003FC87E /* Debug */ = { 630 | isa = XCBuildConfiguration; 631 | buildSettings = { 632 | BUNDLE_LOADER = "$(TEST_HOST)"; 633 | GCC_PREPROCESSOR_DEFINITIONS = ( 634 | "DEBUG=1", 635 | "$(inherited)", 636 | ); 637 | INFOPLIST_FILE = MSRExampleTests/Info.plist; 638 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 639 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 640 | LIBRARY_SEARCH_PATHS = ( 641 | "$(inherited)", 642 | "\"$(SRCROOT)/$(TARGET_NAME)\"", 643 | ); 644 | PRODUCT_NAME = "$(TARGET_NAME)"; 645 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MSRExample.app/MSRExample"; 646 | }; 647 | name = Debug; 648 | }; 649 | 00E356F71AD99517003FC87E /* Release */ = { 650 | isa = XCBuildConfiguration; 651 | buildSettings = { 652 | BUNDLE_LOADER = "$(TEST_HOST)"; 653 | COPY_PHASE_STRIP = NO; 654 | INFOPLIST_FILE = MSRExampleTests/Info.plist; 655 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 656 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 657 | LIBRARY_SEARCH_PATHS = ( 658 | "$(inherited)", 659 | "\"$(SRCROOT)/$(TARGET_NAME)\"", 660 | ); 661 | PRODUCT_NAME = "$(TARGET_NAME)"; 662 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MSRExample.app/MSRExample"; 663 | }; 664 | name = Release; 665 | }; 666 | 13B07F941A680F5B00A75B9A /* Debug */ = { 667 | isa = XCBuildConfiguration; 668 | buildSettings = { 669 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 670 | CURRENT_PROJECT_VERSION = 1; 671 | DEAD_CODE_STRIPPING = NO; 672 | DEVELOPMENT_TEAM = RRS6DX4EXX; 673 | HEADER_SEARCH_PATHS = ( 674 | "$(inherited)", 675 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 676 | "$(SRCROOT)/../node_modules/react-native/React/**", 677 | "$(SRCROOT)/../node_modules/react-native-idtech-msr-audio/ios/**", 678 | ); 679 | INFOPLIST_FILE = MSRExample/Info.plist; 680 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 681 | OTHER_LDFLAGS = ( 682 | "$(inherited)", 683 | "-ObjC", 684 | "-lc++", 685 | ); 686 | PRODUCT_NAME = MSRExample; 687 | VERSIONING_SYSTEM = "apple-generic"; 688 | }; 689 | name = Debug; 690 | }; 691 | 13B07F951A680F5B00A75B9A /* Release */ = { 692 | isa = XCBuildConfiguration; 693 | buildSettings = { 694 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 695 | CURRENT_PROJECT_VERSION = 1; 696 | DEVELOPMENT_TEAM = RRS6DX4EXX; 697 | HEADER_SEARCH_PATHS = ( 698 | "$(inherited)", 699 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 700 | "$(SRCROOT)/../node_modules/react-native/React/**", 701 | "$(SRCROOT)/../node_modules/react-native-idtech-msr-audio/ios/**", 702 | ); 703 | INFOPLIST_FILE = MSRExample/Info.plist; 704 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 705 | OTHER_LDFLAGS = ( 706 | "$(inherited)", 707 | "-ObjC", 708 | "-lc++", 709 | ); 710 | PRODUCT_NAME = MSRExample; 711 | VERSIONING_SYSTEM = "apple-generic"; 712 | }; 713 | name = Release; 714 | }; 715 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 716 | isa = XCBuildConfiguration; 717 | buildSettings = { 718 | ALWAYS_SEARCH_USER_PATHS = NO; 719 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 720 | CLANG_CXX_LIBRARY = "libc++"; 721 | CLANG_ENABLE_MODULES = YES; 722 | CLANG_ENABLE_OBJC_ARC = YES; 723 | CLANG_WARN_BOOL_CONVERSION = YES; 724 | CLANG_WARN_CONSTANT_CONVERSION = YES; 725 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 726 | CLANG_WARN_EMPTY_BODY = YES; 727 | CLANG_WARN_ENUM_CONVERSION = YES; 728 | CLANG_WARN_INT_CONVERSION = YES; 729 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 730 | CLANG_WARN_UNREACHABLE_CODE = YES; 731 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 732 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 733 | COPY_PHASE_STRIP = NO; 734 | ENABLE_STRICT_OBJC_MSGSEND = YES; 735 | GCC_C_LANGUAGE_STANDARD = gnu99; 736 | GCC_DYNAMIC_NO_PIC = NO; 737 | GCC_OPTIMIZATION_LEVEL = 0; 738 | GCC_PREPROCESSOR_DEFINITIONS = ( 739 | "DEBUG=1", 740 | "$(inherited)", 741 | ); 742 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 743 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 744 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 745 | GCC_WARN_UNDECLARED_SELECTOR = YES; 746 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 747 | GCC_WARN_UNUSED_FUNCTION = YES; 748 | GCC_WARN_UNUSED_VARIABLE = YES; 749 | HEADER_SEARCH_PATHS = ( 750 | "$(inherited)", 751 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 752 | "$(SRCROOT)/../node_modules/react-native/React/**", 753 | "$(SRCROOT)/../node_modules/react-native-idtech-msr-audio/ios/**", 754 | ); 755 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 756 | MTL_ENABLE_DEBUG_INFO = YES; 757 | ONLY_ACTIVE_ARCH = YES; 758 | SDKROOT = iphoneos; 759 | }; 760 | name = Debug; 761 | }; 762 | 83CBBA211A601CBA00E9B192 /* Release */ = { 763 | isa = XCBuildConfiguration; 764 | buildSettings = { 765 | ALWAYS_SEARCH_USER_PATHS = NO; 766 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 767 | CLANG_CXX_LIBRARY = "libc++"; 768 | CLANG_ENABLE_MODULES = YES; 769 | CLANG_ENABLE_OBJC_ARC = YES; 770 | CLANG_WARN_BOOL_CONVERSION = YES; 771 | CLANG_WARN_CONSTANT_CONVERSION = YES; 772 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 773 | CLANG_WARN_EMPTY_BODY = YES; 774 | CLANG_WARN_ENUM_CONVERSION = YES; 775 | CLANG_WARN_INT_CONVERSION = YES; 776 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 777 | CLANG_WARN_UNREACHABLE_CODE = YES; 778 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 779 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 780 | COPY_PHASE_STRIP = YES; 781 | ENABLE_NS_ASSERTIONS = NO; 782 | ENABLE_STRICT_OBJC_MSGSEND = YES; 783 | GCC_C_LANGUAGE_STANDARD = gnu99; 784 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 785 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 786 | GCC_WARN_UNDECLARED_SELECTOR = YES; 787 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 788 | GCC_WARN_UNUSED_FUNCTION = YES; 789 | GCC_WARN_UNUSED_VARIABLE = YES; 790 | HEADER_SEARCH_PATHS = ( 791 | "$(inherited)", 792 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 793 | "$(SRCROOT)/../node_modules/react-native/React/**", 794 | "$(SRCROOT)/../node_modules/react-native-idtech-msr-audio/ios/**", 795 | ); 796 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 797 | MTL_ENABLE_DEBUG_INFO = NO; 798 | SDKROOT = iphoneos; 799 | VALIDATE_PRODUCT = YES; 800 | }; 801 | name = Release; 802 | }; 803 | /* End XCBuildConfiguration section */ 804 | 805 | /* Begin XCConfigurationList section */ 806 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "MSRExampleTests" */ = { 807 | isa = XCConfigurationList; 808 | buildConfigurations = ( 809 | 00E356F61AD99517003FC87E /* Debug */, 810 | 00E356F71AD99517003FC87E /* Release */, 811 | ); 812 | defaultConfigurationIsVisible = 0; 813 | defaultConfigurationName = Release; 814 | }; 815 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MSRExample" */ = { 816 | isa = XCConfigurationList; 817 | buildConfigurations = ( 818 | 13B07F941A680F5B00A75B9A /* Debug */, 819 | 13B07F951A680F5B00A75B9A /* Release */, 820 | ); 821 | defaultConfigurationIsVisible = 0; 822 | defaultConfigurationName = Release; 823 | }; 824 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MSRExample" */ = { 825 | isa = XCConfigurationList; 826 | buildConfigurations = ( 827 | 83CBBA201A601CBA00E9B192 /* Debug */, 828 | 83CBBA211A601CBA00E9B192 /* Release */, 829 | ); 830 | defaultConfigurationIsVisible = 0; 831 | defaultConfigurationName = Release; 832 | }; 833 | /* End XCConfigurationList section */ 834 | }; 835 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 836 | } 837 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample.xcodeproj/xcshareddata/xcschemes/MSRExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import "RCTBundleURLProvider.h" 4 | #import "RCTRootView.h" 5 | 6 | @implementation AppDelegate 7 | 8 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 9 | { 10 | NSURL *jsCodeLocation; 11 | 12 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 13 | 14 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 15 | moduleName:@"MSRExample" 16 | initialProperties:nil 17 | launchOptions:launchOptions]; 18 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 19 | 20 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | UIViewController *rootViewController = [UIViewController new]; 22 | rootViewController.view = rootView; 23 | self.window.rootViewController = rootViewController; 24 | [self.window makeKeyAndVisible]; 25 | return YES; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSMicrophoneUsageDescription 6 | Card scanner 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | NSLocationWhenInUseUsageDescription 42 | 43 | NSAppTransportSecurity 44 | 45 | NSExceptionDomains 46 | 47 | localhost 48 | 49 | NSTemporaryExceptionAllowsInsecureHTTPLoads 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MSRExample/ios/MSRExampleTests/MSRExampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import "RCTLog.h" 14 | #import "RCTRootView.h" 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface MSRExampleTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation MSRExampleTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /MSRExample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MSRExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start" 7 | }, 8 | "dependencies": { 9 | "react": "15.3.2", 10 | "react-native": "0.34.1", 11 | "react-native-idtech-msr-audio": "file:.." 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /MSRExample/style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright OnceThere 3 | */ 4 | 5 | import { StyleSheet } from 'react-native'; 6 | 7 | export default StyleSheet.create( { 8 | container: { 9 | flex: 1, 10 | justifyContent: 'center', 11 | alignItems: 'center', 12 | backgroundColor: '#F5FCFF', 13 | }, 14 | titleContainer: { 15 | marginVertical: 20, 16 | }, 17 | titleText: { 18 | fontSize: 20, 19 | textAlign: 'center', 20 | }, 21 | details: { 22 | textAlign: 'center', 23 | color: '#333333', 24 | fontSize: 16, 25 | marginBottom: 5, 26 | }, 27 | button: { 28 | borderWidth: 0.5, 29 | borderRadius: 8, 30 | backgroundColor: 'blue', 31 | padding: 10, 32 | margin: 5, 33 | }, 34 | buttonDisabled: { 35 | backgroundColor: 'grey', 36 | }, 37 | buttonText: { 38 | color: 'white', 39 | }, 40 | }) 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Native ID TECH MagStripe Reader (audio jack) Integration 2 | 3 | This is a React Native library that wraps the [ID Tech MSR audio](http://www.idtechproducts.com/products/mobile-readers/msr-only) [native library](https://atlassian.idtechproducts.com/confluence/display/KB/Shuttle+-+downloads) for communicating with the UniMag I/II/Pro and Shuttle readers. 4 | 5 | iOS and Android are supported. 6 | 7 | ## Installation 8 | 9 | * `npm install https://github.com/oncethere/react-native-idtech-msr-audio --save` 10 | * `react-native link` 11 | 12 | ### iOS setup 13 | * Add _AVFoundation_, _AudioToolbox_, _MediaPlayer_ frameworks to the project (Build Phases -> Link Binary With Libraries) 14 | * Add the `NSMicrophoneUsageDescription` permission to the Info.plist. 15 | 16 | ### Android setup 17 | * Check whether `react-native-link` performed the configuration correctly... 18 | * Add the necessary permissions to `AndroidManifest.xml` : 19 | ``` 20 | 21 | 22 | 23 | 24 | ``` 25 | Note that for Android M and later, you may need to check for permissions at runtime and prompt the user with the [PermissionsAndroid API](https://facebook.github.io/react-native/docs/permissionsandroid.html). 26 | 27 | * Add to `android/settings.gradle` if `react-native link` didn't: 28 | ``` 29 | include ':react-native-idtech-msr-audio' 30 | project(':react-native-idtech-msr-audio').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-idtech-msr-audio/android') 31 | ``` 32 | * Add to `android/app/build.gradle` : 33 | ``` 34 | dependencies { 35 | compile project(':react-native-idtech-msr-audio') 36 | } 37 | ``` 38 | * Add to `MainApplication.java` : 39 | ``` 40 | import com.oncethere.idtechmsraudio.IDTechMSRAudioPackage; 41 | // ... 42 | 43 | public class MainApplication extends Application implements ReactApplication { 44 | 45 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { 46 | 47 | // ... 48 | 49 | @Override 50 | protected List getPackages() { 51 | return Arrays.asList( 52 | new MainReactPackage(), 53 | new IDTechMSRAudioPackage(), 54 | // ... 55 | ); 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | * The preset XML table fetched by the ID Tech library offers limited device support. That is not robust enough for production use, so auto config is leveraged instead. The first time detection will take some time, but subsequent connections use the cached profile which is fast. 62 | 63 | 64 | ### React Native JS usage 65 | * Import the module in a RN app: 66 | `import IDTECH_MSR_audio from 'react-native-idtech-msr-audio';` 67 | * Platform-specific dependencies are listed under the Example section. 68 | 69 | ## API 70 | 71 | All available methods are promise-based: 72 | 73 | * `activate(readerType, swipeTimeout, logging)` -- Start a connection to the card reader. Parameters: 74 | * _readerType_: UniMag1 = 1, UniMagPro = 2, UniMag2 = 3, Shuttle = 4. 75 | * _swipeTimeout_: Set swipe to timeout after n seconds. 0 waits indefinitely. 76 | * _logging_: (bool) Enables info level NSLogs inside SDK. 77 | * `deactivate()` -- End connection to the card reader. 78 | * `swipe()` -- Begin listening for a swipe. Register for events to receive the card swipe data. 79 | 80 | 81 | #### Events 82 | Events are emitted by NativeEventEmitter under the name `IdTechUniMagEvent`. Upon a successful swipe, the response type will be `umSwipe_receivedSwipe` and the _data_ key will be populated. 83 | 84 | #### Example code snippet 85 | ```Javascript 86 | import IDTECH_MSR_audio from 'react-native-idtech-msr-audio'; 87 | import { NativeModules, NativeEventEmitter } from 'react-native'; 88 | 89 | componentDidMount() { 90 | // First subscribe to events from the card reader. 91 | const IdTechUniMagEvent = new NativeEventEmitter(NativeModules.IDTECH_MSR_audio); 92 | this.IdTechUniMagEventSub = IdTechUniMagEvent.addListener( 93 | 'IdTechUniMagEvent', 94 | (response) => { 95 | if (response.type === 'umConnection_connected') { 96 | console.log("Card reader connected. Initiating swipe detection..."); 97 | IDTECH_MSR_audio.swipe(); 98 | } 99 | if (response.type === 'umSwipe_receivedSwipe') { 100 | console.log("Successfully received swipe."); 101 | } 102 | console.log("IDTECH_MSR_audio event notification: " + JSON.stringify(response)); 103 | } 104 | ); 105 | 106 | // Then connect to the card reader. 107 | IDTECH_MSR_audio.activate({ 108 | readerType: 4, //Shuttle 109 | swipeTimeout: 0, // wait indefinitely for swipe 110 | logging: false 111 | }).then( 112 | (response) =>{ 113 | console.log("IDTECH_MSR_audio activation response:" + JSON.stringify(response)); 114 | }); 115 | } 116 | 117 | componentWillUnmount() { 118 | // Both of these calls are necessary to disconnect from the IDTech library. 119 | this.IdTechUniMagEventSub.remove(); 120 | IDTECH_MSR_audio.deactivate(); 121 | } 122 | ``` 123 | 124 | ## Example 125 | The `MSRExample/` directory has a sample project using the IDTECH_MSR_audio library. 126 | 127 | * Install npm dependencies ```npm install``` 128 | * Install React Native CLI globally ```sudo npm install -g react-native-cli``` 129 | * ```react-native link``` 130 | 131 | #### iOS dependencies 132 | * Xcode 133 | * Open `MSRExample/ios/MSRExample.xcworkspace` in Xcode. 134 | * Build and run on a real iOS device. 135 | 136 | 137 | #### Android Dependencies 138 | * ... 139 | 140 | ## ToDo 141 | * Update MSRExample with Android lib 142 | * Tests 143 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | import groovy.json.JsonSlurper 2 | 3 | def computeVersionName() { 4 | // dynamically retrieve version from package.json 5 | def slurper = new JsonSlurper() 6 | def json = slurper.parse(file('../package.json'), "utf-8") 7 | return json.version 8 | } 9 | 10 | buildscript { 11 | repositories { 12 | jcenter() 13 | } 14 | 15 | dependencies { 16 | classpath 'com.android.tools.build:gradle:1.5.0' 17 | } 18 | } 19 | 20 | apply plugin: 'com.android.library' 21 | 22 | android { 23 | compileSdkVersion 23 24 | buildToolsVersion "23.0.1" 25 | 26 | defaultConfig { 27 | minSdkVersion 16 28 | targetSdkVersion 22 29 | versionCode 1 30 | // get version name from package.json version 31 | versionName computeVersionName() 32 | } 33 | lintOptions { 34 | abortOnError false 35 | } 36 | } 37 | 38 | repositories { 39 | mavenCentral() 40 | } 41 | 42 | dependencies { 43 | compile fileTree(dir: "libs", include: ["*.jar"]) 44 | compile 'com.facebook.react:react-native:+' 45 | } 46 | -------------------------------------------------------------------------------- /android/libs/UniMag_SDK_v5.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/android/libs/UniMag_SDK_v5.0.jar -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/src/main/java/com/oncethere/idtechmsraudio/AutoConfigProfile.java: -------------------------------------------------------------------------------- 1 | // 2 | // Serializable AutoConfigProfile 'struct' to handle non-serializable StructConfigParameters 3 | // 4 | // Created by Peace Chen on 4/2/2018. 5 | // Copyright © 2018 OnceThere. All rights reserved. 6 | // 7 | 8 | package com.oncethere.idtechmsraudio; 9 | 10 | import IDTech.MSR.XMLManager.StructConfigParameters; 11 | import com.facebook.react.bridge.ReactApplicationContext; 12 | import com.facebook.react.bridge.WritableMap; 13 | import com.facebook.react.bridge.Arguments; 14 | 15 | import java.io.Serializable; 16 | import android.content.Context; 17 | import java.io.IOException; 18 | import java.io.ObjectOutputStream; 19 | import java.io.ObjectInputStream; 20 | import java.io.FileOutputStream; 21 | import java.io.FileInputStream; 22 | 23 | 24 | public class AutoConfigProfile implements Serializable { 25 | static final String AUTO_CONFIG_FILENAME = "umAutoConfigProfile"; 26 | 27 | public short DirectionOutputWave; 28 | public int FrequencyInput; 29 | public int FrequencyOutput; 30 | public int RecordBufferSize; 31 | public int RecordReadBufferSize; 32 | public int WaveDirection; 33 | public short HighThreshold; 34 | public short LowThreshold; 35 | public short Min; 36 | public short Max; 37 | public int BaudRate; 38 | public short PreambleFactor; 39 | public byte ShuttleChannel; 40 | public short ForceHeadsetPlug; 41 | public short UseVoiceRecognition; 42 | public short VolumeLevelAdjust; 43 | 44 | // Serializes auto config object and saves it to a file 45 | public boolean saveAutoConfigProfile(StructConfigParameters profile, ReactApplicationContext ctx) { 46 | DirectionOutputWave = profile.getDirectionOutputWave(); 47 | FrequencyInput = profile.getFrequenceInput(); 48 | FrequencyOutput = profile.getFrequenceOutput(); 49 | RecordBufferSize = profile.getRecordBufferSize(); 50 | RecordReadBufferSize = profile.getRecordReadBufferSize(); 51 | WaveDirection = profile.getWaveDirection(); 52 | HighThreshold = profile.gethighThreshold(); 53 | LowThreshold = profile.getlowThreshold(); 54 | Min = profile.getMin(); 55 | Max = profile.getMax(); 56 | BaudRate = profile.getBaudRate(); 57 | PreambleFactor = profile.getPreAmbleFactor(); 58 | ShuttleChannel = profile.getShuttleChannel(); 59 | ForceHeadsetPlug = profile.getForceHeadsetPlug(); 60 | UseVoiceRecognition = profile.getUseVoiceRecognition(); 61 | VolumeLevelAdjust = profile.getVolumeLevelAdjust(); 62 | 63 | try { 64 | FileOutputStream fileOutputStream = ctx.openFileOutput(AUTO_CONFIG_FILENAME, Context.MODE_PRIVATE); 65 | ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); 66 | objectOutputStream.writeObject(this); 67 | objectOutputStream.close(); 68 | fileOutputStream.close(); 69 | } catch (IOException e) { 70 | e.printStackTrace(); 71 | return false; 72 | } 73 | 74 | return true; 75 | } 76 | 77 | // Creates an object by reading it from a file 78 | public StructConfigParameters loadAutoConfigProfile(ReactApplicationContext ctx) { 79 | try { 80 | FileInputStream fileInputStream = ctx.openFileInput(AUTO_CONFIG_FILENAME); 81 | ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); 82 | AutoConfigProfile autoConfig = (AutoConfigProfile) objectInputStream.readObject(); 83 | objectInputStream.close(); 84 | fileInputStream.close(); 85 | 86 | StructConfigParameters profile = new StructConfigParameters(); 87 | profile.setDirectionOutputWave(autoConfig.DirectionOutputWave); 88 | profile.setFrequenceInput(autoConfig.FrequencyInput); 89 | profile.setFrequenceOutput(autoConfig.FrequencyOutput); 90 | profile.setRecordBufferSize(autoConfig.RecordBufferSize); 91 | profile.setRecordReadBufferSize(autoConfig.RecordReadBufferSize); 92 | profile.setWaveDirection(autoConfig.WaveDirection); 93 | profile.sethighThreshold(autoConfig.HighThreshold); 94 | profile.setlowThreshold(autoConfig.LowThreshold); 95 | profile.setMin(autoConfig.Min); 96 | profile.setMax(autoConfig.Max); 97 | profile.setBaudRate(autoConfig.BaudRate); 98 | profile.setPreAmbleFactor(autoConfig.PreambleFactor); 99 | profile.setShuttleChannel(autoConfig.ShuttleChannel); 100 | profile.setForceHeadsetPlug(autoConfig.ForceHeadsetPlug); 101 | profile.setUseVoiceRecognition(autoConfig.UseVoiceRecognition); 102 | profile.setVolumeLevelAdjust(autoConfig.VolumeLevelAdjust); 103 | return profile; 104 | } catch (IOException e) { 105 | e.printStackTrace(); 106 | } 107 | catch (ClassNotFoundException e) { 108 | e.printStackTrace(); 109 | } 110 | 111 | return null; 112 | } 113 | 114 | public WritableMap toWritableMap(StructConfigParameters profile) { 115 | WritableMap result = Arguments.createMap(); 116 | result.putString("type", "umAutoConfigProfile"); 117 | result.putString("message", "auto config profile"); 118 | 119 | result.putInt("DirectionOutputWave", profile.getDirectionOutputWave()); 120 | result.putInt("FrequencyInput", profile.getFrequenceInput()); 121 | result.putInt("FrequencyOutput", profile.getFrequenceOutput()); 122 | result.putInt("RecordBufferSize", profile.getRecordBufferSize()); 123 | result.putInt("RecordReadBufferSize", profile.getRecordReadBufferSize()); 124 | result.putInt("WaveDirection", profile.getWaveDirection()); 125 | result.putInt("HighThreshold", profile.gethighThreshold()); 126 | result.putInt("LowThreshold", profile.getlowThreshold()); 127 | result.putInt("Min", profile.getMin()); 128 | result.putInt("Max", profile.getMax()); 129 | result.putInt("BaudRate", profile.getBaudRate()); 130 | result.putInt("PreambleFactor", profile.getPreAmbleFactor()); 131 | result.putInt("ShuttleChannel", profile.getShuttleChannel()); 132 | result.putInt("ForceHeadsetPlug", profile.getForceHeadsetPlug()); 133 | result.putInt("UseVoiceRecognition", profile.getUseVoiceRecognition()); 134 | result.putInt("VolumeLevelAdjust", profile.getVolumeLevelAdjust()); 135 | return result; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /android/src/main/java/com/oncethere/idtechmsraudio/IDTechMSRAudioModule.java: -------------------------------------------------------------------------------- 1 | // 2 | // IDTECH_MSR_audio 3 | // 4 | // Created by Peace Chen on 2/27/2018. 5 | // Copyright © 2018 OnceThere. All rights reserved. 6 | // 7 | 8 | package com.oncethere.idtechmsraudio; 9 | 10 | import IDTech.MSR.XMLManager.StructConfigParameters; 11 | import IDTech.MSR.uniMag.Common; 12 | import IDTech.MSR.uniMag.StateList; 13 | import IDTech.MSR.uniMag.uniMagReader; 14 | import IDTech.MSR.uniMag.uniMagReaderMsg; 15 | import IDTech.MSR.uniMag.UniMagTools.uniMagReaderToolsMsg; 16 | import IDTech.MSR.uniMag.UniMagTools.uniMagSDKTools; 17 | import IDTech.MSR.uniMag.uniMagReader.ReaderType; 18 | 19 | import com.facebook.react.bridge.ReactApplicationContext; 20 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 21 | import com.facebook.react.bridge.ReactMethod; 22 | import com.facebook.react.bridge.WritableArray; 23 | import com.facebook.react.bridge.WritableMap; 24 | import com.facebook.react.bridge.Arguments; 25 | import com.facebook.react.bridge.Promise; 26 | import com.facebook.react.modules.core.DeviceEventManagerModule; 27 | 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import javax.annotation.Nullable; 31 | 32 | public class IDTechMSRAudioModule extends ReactContextBaseJavaModule implements uniMagReaderMsg { 33 | 34 | private uniMagReader _uniMagReader = null; 35 | private ReactApplicationContext _reactContext = null; 36 | private AutoConfigProfile autoConfigProfile = new AutoConfigProfile(); 37 | 38 | 39 | public IDTechMSRAudioModule(ReactApplicationContext reactContext) { 40 | super(reactContext); 41 | _reactContext = reactContext; 42 | } 43 | 44 | @Override 45 | public String getName() { 46 | return "IDTECH_MSR_audio"; 47 | } 48 | 49 | @ReactMethod 50 | public void activate(Integer readerType, Integer swipeTimeout, Boolean logging, Promise promise) { 51 | Integer statusCode = UmRet.UMRET_SUCCESS.getValue(); 52 | String message = ""; 53 | 54 | if (_uniMagReader!=null) { 55 | _uniMagReader.unregisterListen(); 56 | _uniMagReader.release(); 57 | _uniMagReader = null; 58 | } 59 | 60 | ReaderType _readerType; 61 | UmReader umReaderType = UmReader.valueOf(readerType); 62 | switch (umReaderType) { 63 | case UMREADER_UNIMAG_ORIGINAL: 64 | _readerType = ReaderType.UM; 65 | break; 66 | case UMREADER_UNIMAG_PRO: 67 | _readerType = ReaderType.UM_PRO; 68 | break; 69 | case UMREADER_UNIMAG_II: 70 | _readerType = ReaderType.UM_II; 71 | break; 72 | case UMREADER_SHUTTLE: 73 | default: 74 | _readerType = ReaderType.SHUTTLE; 75 | break; 76 | } 77 | 78 | _uniMagReader = new uniMagReader(this, _reactContext, _readerType); 79 | 80 | if (_uniMagReader != null) { 81 | _uniMagReader.registerListen(); 82 | _uniMagReader.setTimeoutOfSwipeCard(swipeTimeout == 0 ? Integer.MAX_VALUE : swipeTimeout); 83 | _uniMagReader.setVerboseLoggingEnable(logging); 84 | 85 | StructConfigParameters acProfile = autoConfigProfile.loadAutoConfigProfile(_reactContext); 86 | 87 | if (acProfile != null) { 88 | sendEvent("IdTechUniMagEvent", autoConfigProfile.toWritableMap(acProfile)); 89 | _uniMagReader.connectWithProfile(acProfile); 90 | message = "Found existing auto config profile."; 91 | } 92 | else { 93 | message = "Starting auto config."; 94 | _uniMagReader.startAutoConfig(true); 95 | 96 | // ID Tech's device profile table is too limited for production use. 97 | // _uniMagReader.setXMLFileNameWithPath("/sdcard/IDT_uniMagCfg.xml"); 98 | // if (_uniMagReader.loadingConfigurationXMLFile(true)) { 99 | // message = "Found existing config file."; 100 | // _uniMagReader.connect(); 101 | // } 102 | } 103 | } 104 | else { 105 | statusCode = UmRet.UMRET_NO_READER.getValue(); 106 | message = "Failed to initialize UniMag"; 107 | } 108 | 109 | WritableMap result = Arguments.createMap(); 110 | result.putInt("statusCode", statusCode); 111 | result.putString("message", message); 112 | promise.resolve(result); 113 | } 114 | 115 | @ReactMethod 116 | public void deactivate(Promise promise) { 117 | if (_uniMagReader != null) { 118 | _uniMagReader.stopSwipeCard(); 119 | _uniMagReader.unregisterListen(); 120 | _uniMagReader.release(); 121 | } 122 | 123 | WritableMap result = Arguments.createMap(); 124 | result.putInt("statusCode", UmRet.UMRET_SUCCESS.getValue()); 125 | result.putString("message", ""); 126 | promise.resolve(result); 127 | } 128 | 129 | @ReactMethod 130 | public void swipe(Promise promise) { 131 | Integer statusCode = UmRet.UMRET_SUCCESS.getValue(); 132 | String message = "Starting swipe..."; 133 | 134 | if (_uniMagReader != null) { 135 | if (_uniMagReader.startSwipeCard()) { 136 | 137 | } 138 | } 139 | else { 140 | statusCode = UmRet.UMRET_NO_READER.getValue(); 141 | message = "Unable to start swipe."; 142 | } 143 | 144 | WritableMap result = Arguments.createMap(); 145 | result.putInt("statusCode", statusCode); 146 | result.putString("message", message); 147 | promise.resolve(result); 148 | } 149 | 150 | 151 | // --------------------------------------------------------------------------- 152 | // Helper methods 153 | private void sendEvent(String eventName, 154 | @Nullable WritableMap params) { 155 | _reactContext 156 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) 157 | .emit(eventName, params); 158 | } 159 | 160 | // --------------------------------------------------------------------------- 161 | // Required callbacks for uniMagReaderMsg 162 | public void onReceiveMsgToConnect() { 163 | WritableMap result = Arguments.createMap(); 164 | result.putString("type", "umConnection_starting"); 165 | result.putString("message", "Starting connection with reader."); 166 | sendEvent("IdTechUniMagEvent", result); 167 | } 168 | 169 | public void onReceiveMsgConnected() { 170 | WritableMap result = Arguments.createMap(); 171 | result.putString("type", "umConnection_connected"); 172 | result.putString("message", "Reader successfully connected."); 173 | sendEvent("IdTechUniMagEvent", result); 174 | } 175 | 176 | public void onReceiveMsgDisconnected() { 177 | WritableMap result = Arguments.createMap(); 178 | result.putString("type", "umConnection_disconnected"); 179 | result.putString("message", "Reader has been disconnected."); 180 | sendEvent("IdTechUniMagEvent", result); 181 | } 182 | 183 | public void onReceiveMsgTimeout(String strTimeoutMsg) { 184 | WritableMap result = Arguments.createMap(); 185 | result.putString("type", "umConnection_timeout"); 186 | result.putString("message", "Connecting with reader timed out. Please try again."); 187 | sendEvent("IdTechUniMagEvent", result); 188 | } 189 | 190 | public void onReceiveMsgToSwipeCard() { 191 | WritableMap result = Arguments.createMap(); 192 | result.putString("type", "umSwipe_starting"); 193 | result.putString("message", "Waiting for card swipe..."); 194 | sendEvent("IdTechUniMagEvent", result); 195 | } 196 | 197 | public void onReceiveMsgCardData(byte flagOfCardData, byte[] cardData) { 198 | WritableArray cardDataArray = Arguments.createArray(); 199 | cardDataArray.pushString(new String(cardData, java.nio.charset.StandardCharsets.ISO_8859_1)); 200 | WritableMap data = Arguments.createMap(); 201 | data.putBoolean("isValid", true); 202 | data.putBoolean("isAesEncrypted", (flagOfCardData & (1L << 1)) != 0 && (flagOfCardData & (1L << 2)) != 0); 203 | data.putArray("tracks", cardDataArray); 204 | 205 | WritableMap result = Arguments.createMap(); 206 | result.putString("type", "umSwipe_receivedSwipe"); 207 | result.putString("message", "Successful card swipe"); 208 | result.putInt("flagOfCardData", flagOfCardData); 209 | result.putMap("data", data); 210 | sendEvent("IdTechUniMagEvent", result); 211 | } 212 | 213 | public void onReceiveMsgProcessingCardData() { 214 | WritableMap result = Arguments.createMap(); 215 | result.putString("type", "umSwipe_processing_card_data"); 216 | result.putString("message", ""); 217 | sendEvent("IdTechUniMagEvent", result); 218 | } 219 | 220 | public void onReceiveMsgToCalibrateReader() { 221 | WritableMap result = Arguments.createMap(); 222 | result.putString("type", "umSwipe_calibrate_card_reader"); 223 | result.putString("message", ""); 224 | sendEvent("IdTechUniMagEvent", result); 225 | } 226 | 227 | public void onReceiveMsgCommandResult(int commandID, byte[] cmdReturn) { 228 | WritableMap result = Arguments.createMap(); 229 | result.putString("type", "umCommand_result"); 230 | result.putString("message", Integer.toString(commandID)); 231 | result.putString("result", new String(cmdReturn, java.nio.charset.StandardCharsets.ISO_8859_1)); 232 | sendEvent("IdTechUniMagEvent", result); 233 | } 234 | 235 | @Deprecated 236 | public void onReceiveMsgSDCardDFailed(String strMSRData) { 237 | WritableMap result = Arguments.createMap(); 238 | result.putString("type", "umSD_card_failed"); 239 | result.putString("message", strMSRData); 240 | sendEvent("IdTechUniMagEvent", result); 241 | } 242 | 243 | public void onReceiveMsgFailureInfo(int index , String strMessage) { 244 | WritableMap result = Arguments.createMap(); 245 | result.putString("type", "umFail"); 246 | result.putString("message", strMessage); 247 | result.putInt("index", index); 248 | sendEvent("IdTechUniMagEvent", result); 249 | } 250 | 251 | public void onReceiveMsgAutoConfigProgress(int progressValue) { 252 | WritableMap result = Arguments.createMap(); 253 | result.putString("type", "umAutoconfig_progress"); 254 | result.putString("message", Integer.toString(progressValue)); 255 | sendEvent("IdTechUniMagEvent", result); 256 | } 257 | 258 | public void onReceiveMsgAutoConfigProgress(int percent, double res, String profileName) { 259 | WritableMap result = Arguments.createMap(); 260 | result.putString("type", "umAutoconfig_progress"); 261 | result.putString("message", Integer.toString(percent)); 262 | result.putDouble("result", res); 263 | result.putString("profileName", profileName); 264 | sendEvent("IdTechUniMagEvent", result); 265 | } 266 | 267 | public void onReceiveMsgAutoConfigCompleted(StructConfigParameters profile) { 268 | if (!autoConfigProfile.saveAutoConfigProfile(profile, _reactContext)) { 269 | WritableMap saveResult = Arguments.createMap(); 270 | saveResult.putString("type", "umAutoconfig_save_failed"); 271 | saveResult.putString("message", "Failed to save auto config profile."); 272 | sendEvent("IdTechUniMagEvent", saveResult); 273 | } 274 | 275 | sendEvent("IdTechUniMagEvent", autoConfigProfile.toWritableMap(profile)); 276 | WritableMap result = Arguments.createMap(); 277 | result.putString("type", "umAutoconfig_complete"); 278 | result.putString("message", "Completed autoconfig. Connecting to reader."); 279 | sendEvent("IdTechUniMagEvent", result); 280 | _uniMagReader.connectWithProfile(profile); 281 | } 282 | 283 | public boolean getUserGrant(int type, String strMessage) { 284 | boolean getUserGranted = false; 285 | switch(type) { 286 | case uniMagReaderMsg.typeToPowerupUniMag: 287 | case uniMagReaderMsg.typeToUpdateXML: 288 | case uniMagReaderMsg.typeToOverwriteXML: 289 | case uniMagReaderMsg.typeToReportToIdtech: 290 | getUserGranted = true; 291 | break; 292 | } 293 | 294 | WritableMap result = Arguments.createMap(); 295 | result.putString("type", "umUser_grant"); 296 | result.putString("message", strMessage); 297 | result.putInt("result", type); 298 | sendEvent("IdTechUniMagEvent", result); 299 | 300 | return getUserGranted; 301 | } 302 | 303 | } 304 | -------------------------------------------------------------------------------- /android/src/main/java/com/oncethere/idtechmsraudio/IDTechMSRAudioPackage.java: -------------------------------------------------------------------------------- 1 | package com.oncethere.idtechmsraudio; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.NativeModule; 5 | import com.facebook.react.bridge.ReactApplicationContext; 6 | import com.facebook.react.uimanager.ViewManager; 7 | 8 | import java.util.ArrayList; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | public class IDTechMSRAudioPackage implements ReactPackage { 13 | 14 | @Override 15 | public List createViewManagers(ReactApplicationContext reactContext) { 16 | return Collections.emptyList(); 17 | } 18 | 19 | @Override 20 | public List createNativeModules(ReactApplicationContext reactContext) { 21 | List modules = new ArrayList<>(); 22 | 23 | modules.add(new IDTechMSRAudioModule(reactContext)); 24 | 25 | return modules; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/oncethere/idtechmsraudio/UmReader.java: -------------------------------------------------------------------------------- 1 | package com.oncethere.idtechmsraudio; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public enum UmReader { 7 | UMREADER_UNKNOWN(0), 8 | UMREADER_UNIMAG_ORIGINAL(1), 9 | UMREADER_UNIMAG_PRO(2), 10 | UMREADER_UNIMAG_II(3), 11 | UMREADER_SHUTTLE(4); 12 | 13 | private int val; 14 | private static Map map = new HashMap<>(); 15 | 16 | private UmReader(int value){ 17 | val = value; 18 | } 19 | 20 | static { 21 | for (UmReader readerType : UmReader.values()) { 22 | map.put(readerType.val, readerType); 23 | } 24 | } 25 | 26 | public static UmReader valueOf(int readerType) { 27 | return (UmReader) map.get(readerType); 28 | } 29 | 30 | public int getValue(){ 31 | return val; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /android/src/main/java/com/oncethere/idtechmsraudio/UmRet.java: -------------------------------------------------------------------------------- 1 | package com.oncethere.idtechmsraudio; 2 | 3 | //Description |Applicable task 4 | // |Connect|Swipe|Cmd|Update 5 | public enum UmRet { 6 | UMRET_SUCCESS(0), //no error, beginning task | * | * | * | * 7 | UMRET_NO_READER(1), //no reader attached | * | * | * | * 8 | UMRET_SDK_BUSY(2), //SDK is doing another task | * | * | * | * 9 | UMRET_MONO_AUDIO(3), //mono audio is enabled | * | | * | 10 | UMRET_ALREADY_CONNECTED(4),//did connection already | * | | | 11 | UMRET_LOW_VOLUME(5), //audio volume is too low | * | | | 12 | UMRET_NOT_CONNECTED(6), //did not do connection | | * | | 13 | UMRET_NOT_APPLICABLE(7), //operation not applicable to the reader type | | | * | 14 | UMRET_INVALID_ARG(8), //invalid argument passed to API | | | * | 15 | UMRET_UF_INVALID_STR(9), //UF wrong string format | | | | * 16 | UMRET_UF_NO_FILE(10), //UF file not found | | | | * 17 | UMRET_UF_INVALID_FILE(11); //UF wrong file format | | | | * 18 | 19 | private int val; 20 | 21 | private UmRet(int value){ 22 | val = value; 23 | } 24 | 25 | public int getValue(){ 26 | return val; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var IDTECH_MSR_audio = require('react-native').NativeModules.IDTECH_MSR_audio; 2 | 3 | module.exports = { 4 | activate: IDTECH_MSR_audio.activate, 5 | deactivate: IDTECH_MSR_audio.deactivate, 6 | swipe: IDTECH_MSR_audio.swipe, 7 | }; 8 | -------------------------------------------------------------------------------- /ios/IDTECH_MSR_audio.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CE91326D1EDF284800ECA08E /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE91326C1EDF284800ECA08E /* MediaPlayer.framework */; }; 11 | CE91326F1EDF285E00ECA08E /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE91326E1EDF285E00ECA08E /* AudioToolbox.framework */; }; 12 | CE9132711EDF286300ECA08E /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9132701EDF286300ECA08E /* AVFoundation.framework */; }; 13 | CE9132731EDF286F00ECA08E /* IDTECH_UniMag.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9132721EDF286F00ECA08E /* IDTECH_UniMag.a */; }; 14 | CE9132761EDF4E1800ECA08E /* utils.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9132751EDF4E1800ECA08E /* utils.m */; }; 15 | CEF167CB1EDF243B00907A04 /* IdTechUniMag.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF167CA1EDF243B00907A04 /* IdTechUniMag.m */; }; 16 | CEF167CF1EDF244C00907A04 /* UMCardData.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF167CD1EDF244B00907A04 /* UMCardData.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | CEAD77561EDF23B000FE9280 /* CopyFiles */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = "include/$(PRODUCT_NAME)"; 24 | dstSubfolderSpec = 16; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | CE91326C1EDF284800ECA08E /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; 33 | CE91326E1EDF285E00ECA08E /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 34 | CE9132701EDF286300ECA08E /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 35 | CE9132721EDF286F00ECA08E /* IDTECH_UniMag.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = IDTECH_UniMag.a; path = "uniMag-SDK/IDTECH_UniMag.a"; sourceTree = ""; }; 36 | CE9132741EDF4E1800ECA08E /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; 37 | CE9132751EDF4E1800ECA08E /* utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utils.m; sourceTree = ""; }; 38 | CEAD77581EDF23B000FE9280 /* libIDTECH_MSR_audio.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libIDTECH_MSR_audio.a; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | CEF167C91EDF243B00907A04 /* IdTechUniMag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdTechUniMag.h; sourceTree = ""; }; 40 | CEF167CA1EDF243B00907A04 /* IdTechUniMag.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IdTechUniMag.m; sourceTree = ""; }; 41 | CEF167CC1EDF244B00907A04 /* UMCardData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UMCardData.h; path = "uniMag-SDK/UMCardData.h"; sourceTree = SOURCE_ROOT; }; 42 | CEF167CD1EDF244B00907A04 /* UMCardData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UMCardData.m; path = "uniMag-SDK/UMCardData.m"; sourceTree = SOURCE_ROOT; }; 43 | CEF167CE1EDF244C00907A04 /* uniMag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = uniMag.h; path = "uniMag-SDK/uniMag.h"; sourceTree = SOURCE_ROOT; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | CEAD77551EDF23B000FE9280 /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | CE9132731EDF286F00ECA08E /* IDTECH_UniMag.a in Frameworks */, 52 | CE9132711EDF286300ECA08E /* AVFoundation.framework in Frameworks */, 53 | CE91326F1EDF285E00ECA08E /* AudioToolbox.framework in Frameworks */, 54 | CE91326D1EDF284800ECA08E /* MediaPlayer.framework in Frameworks */, 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | CE91326B1EDF284800ECA08E /* Frameworks */ = { 62 | isa = PBXGroup; 63 | children = ( 64 | CE9132721EDF286F00ECA08E /* IDTECH_UniMag.a */, 65 | CE9132701EDF286300ECA08E /* AVFoundation.framework */, 66 | CE91326E1EDF285E00ECA08E /* AudioToolbox.framework */, 67 | CE91326C1EDF284800ECA08E /* MediaPlayer.framework */, 68 | ); 69 | name = Frameworks; 70 | sourceTree = ""; 71 | }; 72 | CEAD774F1EDF23B000FE9280 = { 73 | isa = PBXGroup; 74 | children = ( 75 | CEAD775A1EDF23B000FE9280 /* IDTECH_MSR_audio */, 76 | CEAD77591EDF23B000FE9280 /* Products */, 77 | CE91326B1EDF284800ECA08E /* Frameworks */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | CEAD77591EDF23B000FE9280 /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | CEAD77581EDF23B000FE9280 /* libIDTECH_MSR_audio.a */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | CEAD775A1EDF23B000FE9280 /* IDTECH_MSR_audio */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | CE9132741EDF4E1800ECA08E /* utils.h */, 93 | CE9132751EDF4E1800ECA08E /* utils.m */, 94 | CEF167CC1EDF244B00907A04 /* UMCardData.h */, 95 | CEF167CD1EDF244B00907A04 /* UMCardData.m */, 96 | CEF167CE1EDF244C00907A04 /* uniMag.h */, 97 | CEF167C91EDF243B00907A04 /* IdTechUniMag.h */, 98 | CEF167CA1EDF243B00907A04 /* IdTechUniMag.m */, 99 | ); 100 | path = IDTECH_MSR_audio; 101 | sourceTree = ""; 102 | }; 103 | /* End PBXGroup section */ 104 | 105 | /* Begin PBXNativeTarget section */ 106 | CEAD77571EDF23B000FE9280 /* IDTECH_MSR_audio */ = { 107 | isa = PBXNativeTarget; 108 | buildConfigurationList = CEAD77611EDF23B000FE9280 /* Build configuration list for PBXNativeTarget "IDTECH_MSR_audio" */; 109 | buildPhases = ( 110 | CEAD77541EDF23B000FE9280 /* Sources */, 111 | CEAD77551EDF23B000FE9280 /* Frameworks */, 112 | CEAD77561EDF23B000FE9280 /* CopyFiles */, 113 | ); 114 | buildRules = ( 115 | ); 116 | dependencies = ( 117 | ); 118 | name = IDTECH_MSR_audio; 119 | productName = IDTECH_MSR_audio; 120 | productReference = CEAD77581EDF23B000FE9280 /* libIDTECH_MSR_audio.a */; 121 | productType = "com.apple.product-type.library.static"; 122 | }; 123 | /* End PBXNativeTarget section */ 124 | 125 | /* Begin PBXProject section */ 126 | CEAD77501EDF23B000FE9280 /* Project object */ = { 127 | isa = PBXProject; 128 | attributes = { 129 | LastUpgradeCheck = 0830; 130 | ORGANIZATIONNAME = OnceThere; 131 | TargetAttributes = { 132 | CEAD77571EDF23B000FE9280 = { 133 | CreatedOnToolsVersion = 8.3.2; 134 | ProvisioningStyle = Automatic; 135 | }; 136 | }; 137 | }; 138 | buildConfigurationList = CEAD77531EDF23B000FE9280 /* Build configuration list for PBXProject "IDTECH_MSR_audio" */; 139 | compatibilityVersion = "Xcode 3.2"; 140 | developmentRegion = English; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | ); 145 | mainGroup = CEAD774F1EDF23B000FE9280; 146 | productRefGroup = CEAD77591EDF23B000FE9280 /* Products */; 147 | projectDirPath = ""; 148 | projectRoot = ""; 149 | targets = ( 150 | CEAD77571EDF23B000FE9280 /* IDTECH_MSR_audio */, 151 | ); 152 | }; 153 | /* End PBXProject section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | CEAD77541EDF23B000FE9280 /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | CE9132761EDF4E1800ECA08E /* utils.m in Sources */, 161 | CEF167CB1EDF243B00907A04 /* IdTechUniMag.m in Sources */, 162 | CEF167CF1EDF244C00907A04 /* UMCardData.m in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin XCBuildConfiguration section */ 169 | CEAD775F1EDF23B000FE9280 /* Debug */ = { 170 | isa = XCBuildConfiguration; 171 | buildSettings = { 172 | ALWAYS_SEARCH_USER_PATHS = NO; 173 | CLANG_ANALYZER_NONNULL = YES; 174 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 175 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 176 | CLANG_CXX_LIBRARY = "libc++"; 177 | CLANG_ENABLE_MODULES = YES; 178 | CLANG_ENABLE_OBJC_ARC = YES; 179 | CLANG_WARN_BOOL_CONVERSION = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 182 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 183 | CLANG_WARN_EMPTY_BODY = YES; 184 | CLANG_WARN_ENUM_CONVERSION = YES; 185 | CLANG_WARN_INFINITE_RECURSION = YES; 186 | CLANG_WARN_INT_CONVERSION = YES; 187 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 188 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 189 | CLANG_WARN_UNREACHABLE_CODE = YES; 190 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 191 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 192 | COPY_PHASE_STRIP = NO; 193 | DEBUG_INFORMATION_FORMAT = dwarf; 194 | ENABLE_STRICT_OBJC_MSGSEND = YES; 195 | ENABLE_TESTABILITY = YES; 196 | GCC_C_LANGUAGE_STANDARD = gnu99; 197 | GCC_DYNAMIC_NO_PIC = NO; 198 | GCC_NO_COMMON_BLOCKS = YES; 199 | GCC_OPTIMIZATION_LEVEL = 0; 200 | GCC_PREPROCESSOR_DEFINITIONS = ( 201 | "DEBUG=1", 202 | "$(inherited)", 203 | ); 204 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 205 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 206 | GCC_WARN_UNDECLARED_SELECTOR = YES; 207 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 208 | GCC_WARN_UNUSED_FUNCTION = YES; 209 | GCC_WARN_UNUSED_VARIABLE = YES; 210 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 211 | MTL_ENABLE_DEBUG_INFO = YES; 212 | ONLY_ACTIVE_ARCH = YES; 213 | SDKROOT = iphoneos; 214 | }; 215 | name = Debug; 216 | }; 217 | CEAD77601EDF23B000FE9280 /* Release */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | ALWAYS_SEARCH_USER_PATHS = NO; 221 | CLANG_ANALYZER_NONNULL = YES; 222 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 224 | CLANG_CXX_LIBRARY = "libc++"; 225 | CLANG_ENABLE_MODULES = YES; 226 | CLANG_ENABLE_OBJC_ARC = YES; 227 | CLANG_WARN_BOOL_CONVERSION = YES; 228 | CLANG_WARN_CONSTANT_CONVERSION = YES; 229 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 230 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 231 | CLANG_WARN_EMPTY_BODY = YES; 232 | CLANG_WARN_ENUM_CONVERSION = YES; 233 | CLANG_WARN_INFINITE_RECURSION = YES; 234 | CLANG_WARN_INT_CONVERSION = YES; 235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 236 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 237 | CLANG_WARN_UNREACHABLE_CODE = YES; 238 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 239 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 240 | COPY_PHASE_STRIP = NO; 241 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 242 | ENABLE_NS_ASSERTIONS = NO; 243 | ENABLE_STRICT_OBJC_MSGSEND = YES; 244 | GCC_C_LANGUAGE_STANDARD = gnu99; 245 | GCC_NO_COMMON_BLOCKS = YES; 246 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 247 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 248 | GCC_WARN_UNDECLARED_SELECTOR = YES; 249 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 250 | GCC_WARN_UNUSED_FUNCTION = YES; 251 | GCC_WARN_UNUSED_VARIABLE = YES; 252 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 253 | MTL_ENABLE_DEBUG_INFO = NO; 254 | SDKROOT = iphoneos; 255 | VALIDATE_PRODUCT = YES; 256 | }; 257 | name = Release; 258 | }; 259 | CEAD77621EDF23B000FE9280 /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | HEADER_SEARCH_PATHS = ( 263 | "$(SRCROOT)/../node_modules/react-native/React/**", 264 | "$(SRCROOT)/../../react-native/React/**", 265 | ); 266 | LIBRARY_SEARCH_PATHS = ( 267 | "$(inherited)", 268 | "$(PROJECT_DIR)/uniMag-SDK", 269 | ); 270 | OTHER_LDFLAGS = "-ObjC"; 271 | PRODUCT_NAME = "$(TARGET_NAME)"; 272 | SKIP_INSTALL = YES; 273 | }; 274 | name = Debug; 275 | }; 276 | CEAD77631EDF23B000FE9280 /* Release */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | HEADER_SEARCH_PATHS = ( 280 | "$(SRCROOT)/../node_modules/react-native/React/**", 281 | "$(SRCROOT)/../../react-native/React/**", 282 | ); 283 | LIBRARY_SEARCH_PATHS = ( 284 | "$(inherited)", 285 | "$(PROJECT_DIR)/uniMag-SDK", 286 | ); 287 | OTHER_LDFLAGS = "-ObjC"; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | SKIP_INSTALL = YES; 290 | }; 291 | name = Release; 292 | }; 293 | /* End XCBuildConfiguration section */ 294 | 295 | /* Begin XCConfigurationList section */ 296 | CEAD77531EDF23B000FE9280 /* Build configuration list for PBXProject "IDTECH_MSR_audio" */ = { 297 | isa = XCConfigurationList; 298 | buildConfigurations = ( 299 | CEAD775F1EDF23B000FE9280 /* Debug */, 300 | CEAD77601EDF23B000FE9280 /* Release */, 301 | ); 302 | defaultConfigurationIsVisible = 0; 303 | defaultConfigurationName = Release; 304 | }; 305 | CEAD77611EDF23B000FE9280 /* Build configuration list for PBXNativeTarget "IDTECH_MSR_audio" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | CEAD77621EDF23B000FE9280 /* Debug */, 309 | CEAD77631EDF23B000FE9280 /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | /* End XCConfigurationList section */ 315 | }; 316 | rootObject = CEAD77501EDF23B000FE9280 /* Project object */; 317 | } 318 | -------------------------------------------------------------------------------- /ios/IDTECH_MSR_audio/IdTechUniMag.h: -------------------------------------------------------------------------------- 1 | // 2 | // IdTechUniMag.h 3 | // IDTECH_MSR_audio 4 | // 5 | // Created by Peace Chen on 5/30/2017. 6 | // Copyright © 2017 OnceThere. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "uniMag.h" 11 | #import "UMCardData.h" 12 | #import "utils.h" 13 | 14 | #if __has_include() 15 | // React Native >= 0.40 16 | #import 17 | #import 18 | #import 19 | #else 20 | // React Native <= 0.39 21 | #import "RCTConvert.h" 22 | #import "RCTEventEmitter.h" 23 | #import "RCTBridgeModule.h" 24 | #endif 25 | 26 | @interface IDTECH_MSR_audio : RCTEventEmitter 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ios/IDTECH_MSR_audio/IdTechUniMag.m: -------------------------------------------------------------------------------- 1 | // 2 | // IdTechUniMag.m 3 | // IDTECH_MSR_audio 4 | // 5 | // Created by Peace Chen on 5/30/2017. 6 | // Copyright © 2017 OnceThere. All rights reserved. 7 | // 8 | 9 | #import "IdTechUniMag.h" 10 | 11 | uniMag *uniReader; 12 | static NSMutableArray *s_noteAndSel_t = nil; 13 | 14 | @implementation IDTECH_MSR_audio 15 | 16 | RCT_EXPORT_MODULE() 17 | 18 | RCT_REMAP_METHOD(activate, 19 | readerType:(NSInteger)readerType 20 | swipeTimeout:(NSInteger)swipeTimeout 21 | logging:(BOOL)logging 22 | activate_resolver:(RCTPromiseResolveBlock)resolve 23 | activate_rejecter:(RCTPromiseRejectBlock)reject) 24 | { 25 | //register observers for all uniMag notifications 26 | [self umsdk_registerObservers:TRUE]; 27 | 28 | //enable info level NSLogs inside SDK 29 | // Here we turn on before initializing SDK object so the act of initializing is logged 30 | [uniMag enableLogging:logging]; 31 | 32 | //initialize the SDK by creating a uniMag class object 33 | uniReader = [[uniMag alloc] init]; 34 | 35 | //Set the reader type. The default is UniMag Pro. 36 | uniReader.readerType = (UmReader)readerType; 37 | 38 | //set SDK to perform the connect task automatically when headset is attached 39 | [uniReader setAutoConnect:TRUE]; 40 | 41 | //set swipe timeout (0=infinite). By default, swipe task will timeout after 20 seconds 42 | [uniReader setSwipeTimeoutDuration:swipeTimeout]; 43 | 44 | //make SDK maximize the volume automatically during connection 45 | [uniReader setAutoAdjustVolume:TRUE]; 46 | 47 | UmRet ret = [uniReader startUniMag: TRUE]; 48 | 49 | resolve(@{@"statusCode": @(ret), 50 | @"message": getUmReturnString(ret)} ); 51 | } 52 | 53 | RCT_REMAP_METHOD(deactivate, 54 | deactivate_resolver:(RCTPromiseResolveBlock)resolve 55 | deactivate_rejecter:(RCTPromiseRejectBlock)reject) 56 | { 57 | //deallocating the uniMag object deactivates the uniMag SDK 58 | //[uniReader release]; 59 | uniReader = nil; 60 | 61 | //it is the responsibility of SDK client to unregister itself as notification observer 62 | [self umsdk_registerObservers:FALSE]; 63 | 64 | resolve(@{@"statusCode": @0, 65 | @"message": @""} ); 66 | } 67 | 68 | RCT_REMAP_METHOD(swipe, 69 | swipe_resolver:(RCTPromiseResolveBlock)resolve 70 | swipe_rejecter:(RCTPromiseRejectBlock)reject) 71 | { 72 | //start the swipe task. ie, cause SDK to start waiting for a swipe to be made 73 | UmRet ret = [uniReader requestSwipe]; 74 | 75 | resolve(@{@"statusCode": @(ret), 76 | @"message": getUmReturnString(ret)} ); 77 | } 78 | 79 | //----------------------------------------------------------------------------- 80 | #pragma mark - uniMag SDK notification registration - 81 | //----------------------------------------------------------------------------- 82 | 83 | -(void) umsdk_registerObservers:(BOOL) reg { 84 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 85 | 86 | if (nil == s_noteAndSel_t) { 87 | s_noteAndSel_t = [[NSMutableArray alloc] init]; 88 | //NSAutoreleasePool* pool=[[NSAutoreleasePool alloc] init]; 89 | noteAndSel_t * cd01 = [[noteAndSel_t alloc] init]; 90 | noteAndSel_t * cd02 = [[noteAndSel_t alloc] init]; 91 | noteAndSel_t * cd03 = [[noteAndSel_t alloc] init]; 92 | noteAndSel_t * cd04 = [[noteAndSel_t alloc] init]; 93 | noteAndSel_t * cd05 = [[noteAndSel_t alloc] init]; 94 | noteAndSel_t * cd06 = [[noteAndSel_t alloc] init]; 95 | noteAndSel_t * cd07 = [[noteAndSel_t alloc] init]; 96 | noteAndSel_t * cd08 = [[noteAndSel_t alloc] init]; 97 | noteAndSel_t * cd09 = [[noteAndSel_t alloc] init]; 98 | noteAndSel_t * cd10 = [[noteAndSel_t alloc] init]; 99 | noteAndSel_t * cd11 = [[noteAndSel_t alloc] init]; 100 | noteAndSel_t * cd12 = [[noteAndSel_t alloc] init]; 101 | noteAndSel_t * cd13 = [[noteAndSel_t alloc] init]; 102 | noteAndSel_t * cd14 = [[noteAndSel_t alloc] init]; 103 | noteAndSel_t * cd15 = [[noteAndSel_t alloc] init]; 104 | noteAndSel_t * cd16 = [[noteAndSel_t alloc] init]; 105 | noteAndSel_t * cd17 = [[noteAndSel_t alloc] init]; 106 | [cd01 setV: uniMagAttachmentNotification : @selector(umDevice_attachment:)]; 107 | [cd02 setV: uniMagDetachmentNotification : @selector(umDevice_detachment:)]; 108 | [cd03 setV: uniMagInsufficientPowerNotification: @selector(umConnection_lowVolume:)]; 109 | [cd04 setV: uniMagMonoAudioErrorNotification : @selector(umConnection_monoAudioError:)]; 110 | [cd05 setV: uniMagPoweringNotification : @selector(umConnection_starting:)]; 111 | [cd06 setV: uniMagTimeoutNotification : @selector(umConnection_timeout:)]; 112 | [cd07 setV: uniMagDidConnectNotification : @selector(umConnection_connected:)]; 113 | [cd08 setV: uniMagDidDisconnectNotification : @selector(umConnection_disconnected:)]; 114 | [cd09 setV: uniMagSwipeNotification : @selector(umSwipe_starting:)]; 115 | [cd10 setV: uniMagTimeoutSwipeNotification : @selector(umSwipe_timeout:)]; 116 | [cd11 setV: uniMagDataProcessingNotification : @selector(umDataProcessing:)]; 117 | [cd12 setV: uniMagInvalidSwipeNotification : @selector(umSwipe_invalid:)]; 118 | [cd13 setV: uniMagDidReceiveDataNotification : @selector(umSwipe_receivedSwipe:)]; 119 | [cd14 setV: uniMagCmdSendingNotification : @selector(umCommand_starting:)]; 120 | [cd15 setV: uniMagCommandTimeoutNotification : @selector(umCommand_timeout:)]; 121 | [cd16 setV: uniMagDidReceiveCmdNotification : @selector(umCommand_receivedResponse:)]; 122 | [cd17 setV: uniMagSystemMessageNotification : @selector(umSystemMessage:)]; 123 | [s_noteAndSel_t addObject: cd01]; 124 | [s_noteAndSel_t addObject: cd02]; 125 | [s_noteAndSel_t addObject: cd03]; 126 | [s_noteAndSel_t addObject: cd04]; 127 | [s_noteAndSel_t addObject: cd05]; 128 | [s_noteAndSel_t addObject: cd06]; 129 | [s_noteAndSel_t addObject: cd07]; 130 | [s_noteAndSel_t addObject: cd08]; 131 | [s_noteAndSel_t addObject: cd09]; 132 | [s_noteAndSel_t addObject: cd10]; 133 | [s_noteAndSel_t addObject: cd11]; 134 | [s_noteAndSel_t addObject: cd12]; 135 | [s_noteAndSel_t addObject: cd13]; 136 | [s_noteAndSel_t addObject: cd14]; 137 | [s_noteAndSel_t addObject: cd15]; 138 | [s_noteAndSel_t addObject: cd16]; 139 | [s_noteAndSel_t addObject: cd17]; 140 | //[pool drain]; 141 | } 142 | 143 | int len = (int)s_noteAndSel_t.count; 144 | //register or unregister 145 | for (int i=0; i *)supportedEvents { 161 | return @[@"IdTechUniMagEvent"]; 162 | } 163 | 164 | #pragma mark attachment 165 | 166 | //called when uniMag is physically attached 167 | - (void)umDevice_attachment:(NSNotification *)notification { 168 | [self sendEventWithName:@"IdTechUniMagEvent" 169 | body:@{@"type": @"umDevice_attachment", 170 | @"message": @"Reader has been plugged in."}]; 171 | } 172 | 173 | //called when uniMag is physically detached 174 | - (void)umDevice_detachment:(NSNotification *)notification { 175 | [self sendEventWithName:@"IdTechUniMagEvent" 176 | body:@{@"type": @"umDevice_detachment", 177 | @"message": @"Reader has been unplugged."}]; 178 | } 179 | 180 | #pragma mark connection task 181 | 182 | //called when attempting to start the connection task but iDevice's headphone playback volume is too low 183 | - (void)umConnection_lowVolume:(NSNotification *)notification { 184 | [self sendEventWithName:@"IdTechUniMagEvent" 185 | body:@{@"type": @"umConnection_lowVolume", 186 | @"message": @"Volume too low. Please maximize volume then re-attach the reader."}]; 187 | } 188 | 189 | //called when attempting to start a task but iDevice's mono audio accessibility 190 | // feature is enabled 191 | - (void)umConnection_monoAudioError:(NSNotification *)notification { 192 | [self sendEventWithName:@"IdTechUniMagEvent" 193 | body:@{@"type": @"umConnection_monoAudioError", 194 | @"message": @"Mono audio setting is enabled. Please disable it from iOS's Settings app."}]; 195 | } 196 | 197 | //called when successfully starting the connection task 198 | - (void)umConnection_starting:(NSNotification *)notification { 199 | [self sendEventWithName:@"IdTechUniMagEvent" 200 | body:@{@"type": @"umConnection_starting", 201 | @"message": @"Starting connection with reader."}]; 202 | } 203 | 204 | //called when SDK failed to handshake with reader in time. ie, the connection task has timed out 205 | - (void)umConnection_timeout:(NSNotification *)notification { 206 | [self sendEventWithName:@"IdTechUniMagEvent" 207 | body:@{@"type": @"umConnection_timeout", 208 | @"message": @"Connecting with reader timed out. Please try again."}]; 209 | } 210 | 211 | //called when the connection task is successful. SDK's connection state changes to true 212 | - (void)umConnection_connected:(NSNotification *)notification { 213 | [self sendEventWithName:@"IdTechUniMagEvent" 214 | body:@{@"type": @"umConnection_connected", 215 | @"message": @"Reader successfully connected."}]; 216 | } 217 | 218 | //called when SDK's connection state changes to false. This happens when reader becomes 219 | // physically detached or when a disconnect API is called 220 | - (void)umConnection_disconnected:(NSNotification *)notification { 221 | [self sendEventWithName:@"IdTechUniMagEvent" 222 | body:@{@"type": @"umConnection_disconnected", 223 | @"message": @"Reader has been disconnected."}]; 224 | } 225 | 226 | #pragma mark swipe task 227 | 228 | //called when the swipe task is successfully starting, meaning the SDK starts to 229 | // wait for a swipe to be made 230 | - (void)umSwipe_starting:(NSNotification *)notification { 231 | [self sendEventWithName:@"IdTechUniMagEvent" 232 | body:@{@"type": @"umSwipe_starting", 233 | @"message": @"Waiting for card swipe..."}]; 234 | } 235 | 236 | 237 | //called when the SDK hasn't received a swipe from the device within a configured 238 | // "swipe timeout interval". 239 | - (void)umSwipe_timeout:(NSNotification *)notification { 240 | [self sendEventWithName:@"IdTechUniMagEvent" 241 | body:@{@"type": @"umSwipe_timeout", 242 | @"message": @"Swipe timed out. Please try again."}]; 243 | } 244 | 245 | //called when the SDK has read something from the uniMag device 246 | // (eg a swipe, a response to a command) and is in the process of decoding it 247 | // Use this to provide an early feedback on the UI 248 | - (void)umDataProcessing:(NSNotification *)notification { 249 | [self sendEventWithName:@"IdTechUniMagEvent" 250 | body:@{@"type": @"umDataProcessing", 251 | @"message": @"Processing swipe..."}]; 252 | } 253 | 254 | //called when SDK failed to read a valid card swipe 255 | - (void)umSwipe_invalid:(NSNotification *)notification { 256 | [self sendEventWithName:@"IdTechUniMagEvent" 257 | body:@{@"type": @"umSwipe_invalid", 258 | @"message": @"Failed to read a valid swipe. Please try again."}]; 259 | } 260 | 261 | //called when SDK received a swipe successfully 262 | - (void)umSwipe_receivedSwipe:(NSNotification *)notification { 263 | NSData *data = [notification object]; 264 | UMCardData *cd = [[UMCardData alloc] initWithBytes:data]; 265 | 266 | // RCTConvert-serializable object 267 | NSObject * swipeData; 268 | if (cd.isAesEncrypted) { 269 | NSString *track1 = [[NSString alloc] initWithData:cd.track1 encoding:NSUTF8StringEncoding]; 270 | NSString *track2 = [[NSString alloc] initWithData:cd.track2 encoding:NSUTF8StringEncoding]; 271 | NSString *track3 = [[NSString alloc] initWithData:cd.track3 encoding:NSUTF8StringEncoding]; 272 | NSString *track1_encrypted = [[NSString alloc] initWithData:cd.track1_encrypted encoding:NSUTF8StringEncoding]; 273 | NSString *track2_encrypted = [[NSString alloc] initWithData:cd.track2_encrypted encoding:NSUTF8StringEncoding]; 274 | NSString *track3_encrypted = [[NSString alloc] initWithData:cd.track3_encrypted encoding:NSUTF8StringEncoding]; 275 | 276 | swipeData = @{ 277 | @"isValid": [NSNumber numberWithBool:cd.isValid], 278 | @"isAesEncrypted": [NSNumber numberWithBool:cd.isAesEncrypted], 279 | @"tracks": @[track1, track2, track3], 280 | @"tracks_encrypted": @[track1_encrypted, track2_encrypted, track3_encrypted], 281 | @"serialNumber": [[NSString alloc] initWithData:cd.serialNumber encoding:NSUTF8StringEncoding], 282 | @"KSN": [[NSString alloc] initWithData:cd.KSN encoding:NSUTF8StringEncoding] 283 | }; 284 | } 285 | else { 286 | swipeData = @{ 287 | @"isValid": [NSNumber numberWithBool:cd.isValid], 288 | @"isAesEncrypted": [NSNumber numberWithBool:cd.isAesEncrypted], 289 | @"tracks": @[ [[NSString alloc] initWithData:cd.byteData encoding:NSUTF8StringEncoding] ] 290 | }; 291 | } 292 | 293 | [self sendEventWithName:@"IdTechUniMagEvent" 294 | body:@{@"type": @"umSwipe_receivedSwipe", 295 | @"message": @"Successful swipe.", 296 | @"data": swipeData}]; 297 | } 298 | 299 | #pragma mark command task 300 | 301 | //called when SDK successfully starts to send a command. SDK starts the command 302 | // task 303 | - (void)umCommand_starting:(NSNotification *)notification { 304 | #ifdef DEBUG 305 | NSData *data = [notification object]; 306 | [self sendEventWithName:@"IdTechUniMagEvent" 307 | body:@{@"type": @"umCommand_starting", 308 | @"message": repr(data)}]; 309 | #endif 310 | } 311 | 312 | //called when SDK failed to receive a command response within a configured 313 | // "command timeout interval" 314 | - (void)umCommand_timeout:(NSNotification *)notification { 315 | #ifdef DEBUG 316 | [self sendEventWithName:@"IdTechUniMagEvent" 317 | body:@{@"type": @"umCommand_timeout", 318 | @"message": @"Command timed out. Please try again."}]; 319 | #endif 320 | } 321 | 322 | //called when SDK successfully received a response to a command 323 | - (void)umCommand_receivedResponse:(NSNotification *)notification { 324 | #ifdef DEBUG 325 | NSData *data = [notification object]; 326 | [self sendEventWithName:@"IdTechUniMagEvent" 327 | body:@{@"type": @"umCommand_receivedResponse", 328 | @"message": repr(data)}]; 329 | #endif 330 | } 331 | 332 | #pragma mark misc 333 | 334 | //this is a observer for a generic and extensible notification. It's currently only used during firmware update 335 | - (void) umSystemMessage:(NSNotification *)notification { 336 | NSError *err = nil; 337 | err = [notification object]; 338 | NSString *sysMsg = [NSString stringWithFormat: 339 | @"%ld: %@", (long)[err code], [[err userInfo] valueForKey:NSLocalizedDescriptionKey]]; 340 | 341 | [self sendEventWithName:@"IdTechUniMagEvent" 342 | body:@{@"type": @"umSystemMessage", 343 | @"message": sysMsg} ]; 344 | } 345 | 346 | @end 347 | -------------------------------------------------------------------------------- /ios/IDTECH_MSR_audio/utils.h: -------------------------------------------------------------------------------- 1 | #import "uniMag.h" 2 | 3 | NSString* repr(NSData* byteArray); 4 | NSString* getUmReturnString(UmRet ret); 5 | 6 | // ------------------------------------------------------------------------- 7 | // Used by umsdk_registerObservers ---- uniMag SDK notification registration 8 | // ------------------------------------------------------------------------- 9 | @interface noteAndSel_t : NSObject 10 | { 11 | } 12 | @property (nonatomic, retain) NSString *n; 13 | @property (nonatomic, assign) SEL s; 14 | 15 | -(void) setV: (NSString *) _nn : (SEL) _ss; 16 | @end 17 | -------------------------------------------------------------------------------- /ios/IDTECH_MSR_audio/utils.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "utils.h" 3 | 4 | //get C source code representation of a byte string 5 | NSString* repr(NSData* byteArray) { 6 | NSMutableString * ret = [NSMutableString string]; 7 | 8 | @autoreleasepool 9 | { 10 | const int len = (int)byteArray.length; 11 | const Byte *bytes = byteArray.bytes; 12 | NSString *chr=nil; 13 | char oneCharStr[2] = {0,0}; 14 | 15 | for (int i=0; i= 0x20 && bytes[i] <= 0x7E) { 29 | oneCharStr[0] = bytes[i]; 30 | chr = [NSString stringWithCString:oneCharStr encoding:NSASCIIStringEncoding]; 31 | } 32 | //normal escaped char eg 0xab => \xab 33 | else { 34 | chr = [NSString stringWithFormat:@"\\x%02x", bytes[i]]; 35 | } 36 | 37 | // 38 | [ret appendString: chr]; 39 | } 40 | } 41 | 42 | return ret; 43 | } 44 | 45 | NSString* getUmReturnString(UmRet ret) { 46 | NSString *s; 47 | do { 48 | switch (ret) { 49 | case UMRET_SUCCESS : s=@""; break; 50 | case UMRET_NO_READER : s=@"No reader attached"; break; 51 | case UMRET_SDK_BUSY : s=@"Communication with reader in progress"; break; 52 | case UMRET_MONO_AUDIO : s=@"Mono audio enabled"; break; 53 | case UMRET_ALREADY_CONNECTED: s=@"Already connected"; break; 54 | case UMRET_LOW_VOLUME : s=@"Low volume"; break; 55 | case UMRET_NOT_CONNECTED : s=@"Not connected"; break; 56 | case UMRET_NOT_APPLICABLE : s=@"Not applicable to reader type"; break; 57 | case UMRET_INVALID_ARG : s=@"Invalid argument"; break; 58 | case UMRET_UF_INVALID_STR : s=@"Invalid firmware update string"; break; 59 | case UMRET_UF_NO_FILE : s=@"Firmware file not found"; break; 60 | case UMRET_UF_INVALID_FILE : s=@"Invalid firmware file"; break; 61 | default: s=@""; break; 62 | } 63 | } while (0); 64 | 65 | return s; 66 | } 67 | 68 | // ------------------------------------------------------------------------- 69 | // Used by umsdk_registerObservers --- uniMag SDK notification registration 70 | // ------------------------------------------------------------------------- 71 | @implementation noteAndSel_t 72 | @synthesize n = _n; 73 | @synthesize s = _s; 74 | 75 | -(id) init { 76 | self = [super init]; 77 | if (self) { 78 | _n = @""; 79 | _s = nil; 80 | } 81 | return self; 82 | } 83 | 84 | -(void) setV: (NSString *) _nn : (SEL) _ss; 85 | { 86 | _n = _nn; 87 | _s = _ss; 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /ios/uniMag-SDK/IDTECH_UniMag.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oncethere/react-native-idtech-msr-audio/598fcda5c4f6a31b3495eee38521b92fbcf6bb27/ios/uniMag-SDK/IDTECH_UniMag.a -------------------------------------------------------------------------------- /ios/uniMag-SDK/UMCardData.h: -------------------------------------------------------------------------------- 1 | /* 2 | This class parses raw card swipe data produced by a UniMag family card reader. 3 | -UniMag family readers read ISO/IEC 7811 and other types of magnetic stripe cards. Cards have at most 3 "tracks" of data. 4 | -Data format can be either encrypted or or unencrypted 5 | -If property "isValid" is true, no problem was found during parsing. 6 | */ 7 | 8 | #import 9 | 10 | @interface UMCardData : NSObject 11 | 12 | //Raw data 13 | @property (readonly) NSData *byteData; //Raw data which was used to initialize this object. 14 | 15 | //Meta 16 | @property (readonly) BOOL isValid; //All available fields were successfully parsed from the raw data 17 | @property (readonly) BOOL isEncrypted; //Whether the output is from an encrypting reader or a non-encrypting reader 18 | @property (readonly) BOOL isAesEncrypted; //Only valid if isEncrypted==TRUE. If true, AES cipher is used, otherwise it's TDES 19 | 20 | //Parsed parts. Even if isValid==TRUE, some fields may be nil if the reader did not output them. 21 | // For example, reader may not read all tracks of a card. 22 | 23 | // Tracks 24 | // If non-encrypting reader is used, it is the full plain text card data 25 | // If encrypting reader is used, it is the partially masked plain text card data 26 | @property (readonly) NSData *track1; 27 | @property (readonly) NSData *track2; 28 | @property (readonly) NSData *track3; 29 | 30 | // Encrypted Tracks. Only in encrypting reader output 31 | @property (readonly) NSData *track1_encrypted; 32 | @property (readonly) NSData *track2_encrypted; 33 | @property (readonly) NSData *track3_encrypted; 34 | 35 | // Other. Only in encrypting reader output 36 | @property (readonly) NSData *serialNumber; 37 | @property (readonly) NSData *KSN; 38 | 39 | 40 | //Init 41 | - (id)initWithBytes: (NSData*)cardData; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ios/uniMag-SDK/UMCardData.m: -------------------------------------------------------------------------------- 1 | 2 | #import "UMCardData.h" 3 | 4 | //------------------------------------------------------------------------------ 5 | #pragma mark - Utilities 6 | //------------------------------------------------------------------------------ 7 | 8 | static BOOL isBitSet(Byte byte, int bitIndex) { 9 | Byte mask = (1 << bitIndex); 10 | return byte & mask; 11 | } 12 | 13 | //------------------------------------------------------------------------------ 14 | #pragma mark - Initialize 15 | //------------------------------------------------------------------------------ 16 | 17 | @implementation UMCardData 18 | 19 | @synthesize byteData =_byteData; 20 | 21 | @synthesize isValid =_isValid; 22 | @synthesize isEncrypted =_isEncrypted; 23 | @synthesize isAesEncrypted =_isAesEncrypted; 24 | 25 | @synthesize track1=_track1; 26 | @synthesize track2=_track2; 27 | @synthesize track3=_track3; 28 | @synthesize track1_encrypted=_track1_encrypted; 29 | @synthesize track2_encrypted=_track2_encrypted; 30 | @synthesize track3_encrypted=_track3_encrypted; 31 | 32 | @synthesize serialNumber=_serialNumber; 33 | @synthesize KSN=_KSN; 34 | 35 | /* 36 | - (void)dealloc { 37 | [_byteData release]; 38 | 39 | [_track1 release]; 40 | [_track2 release]; 41 | [_track3 release]; 42 | [_track1_encrypted release]; 43 | [_track2_encrypted release]; 44 | [_track3_encrypted release]; 45 | 46 | [_serialNumber release]; 47 | [_KSN release]; 48 | 49 | [super dealloc]; 50 | } 51 | */ 52 | 53 | - (id)initWithBytes: (NSData*)cardData { 54 | self = [super init]; 55 | if (self && cardData) { 56 | self->_byteData = [cardData copy]; 57 | 58 | const UInt8 *bytes= cardData.bytes; 59 | const NSUInteger len = cardData.length; 60 | 61 | //check validity and parse 62 | if (len >= 1) { 63 | //is valid encrypted swipe? 64 | if (bytes[0] == '\x02') { 65 | self->_isEncrypted = TRUE; 66 | [self verifyAndParse_encrypted: cardData]; 67 | } 68 | //is valid unencrypted swipe? 69 | else { 70 | self->_isEncrypted = FALSE; 71 | [self verifyAndParse_unencrypted: cardData]; 72 | } 73 | } 74 | } 75 | return self; 76 | } 77 | 78 | -(void) verifyAndParse_encrypted:(NSData*) cardData { 79 | /* 80 | Encrypted swipe format: STX LenL LenH CheckXor CheckSum ETX 81 | The rest... there's a document. 82 | */ 83 | 84 | //things to fill out 85 | NSData *tracks [3] = {nil, nil, nil}; 86 | NSData *tracks_enc[3] = {nil, nil, nil}; 87 | NSData *serialNumber = nil; 88 | NSData *ksn = nil; 89 | BOOL isAES = FALSE; //true if AES, false if TDES 90 | BOOL isSwipeDataValid = FALSE; 91 | 92 | //shorthand 93 | const UInt8 *bytes= cardData.bytes; 94 | const NSUInteger len = cardData.length; 95 | 96 | //Verify 97 | if (len < 6) 98 | return; 99 | // STX ETX 100 | if (bytes[0 ] != '\x02' || 101 | bytes[len-1] != '\x03' ) 102 | return; 103 | // Length 104 | int payloadLen = 105 | (bytes[2]<<8)+ 106 | (bytes[1] ); 107 | if (payloadLen+6 != len) 108 | return; 109 | // CheckXor and CheckSum 110 | UInt8 cksum=0, ckxor=0; 111 | for (int i=3; i len-3) goto stopParse;} 122 | int idx = 0; 123 | 124 | //get track1, track2, track3 length 125 | int trackLens[3]; 126 | idx = 5; 127 | CHECK_INDEX(idx+3); 128 | for (int i=0; i<3; i++) 129 | trackLens[i] = bytes[idx+i]; 130 | 131 | //get masked track 132 | int trackLensSum=0; 133 | idx = 10; 134 | for (int i=0; i<3; i++) { 135 | //skip if len is 0 or presence flag not set 136 | if ( trackLens[i]==0 || !isBitSet(bytes[8],i) ) 137 | continue; 138 | CHECK_INDEX(idx + trackLens[i]); 139 | tracks[i] = [cardData subdataWithRange: NSMakeRange(idx, trackLens[i])]; 140 | idx += trackLens[i]; 141 | trackLensSum += trackLens[i]; 142 | } 143 | 144 | //determine encryption type (TDES or AES) 145 | idx = 8; 146 | CHECK_INDEX(idx+1); 147 | Byte encType = ((bytes[idx]>>4) & 0x03); 148 | if (encType == 0x00) 149 | isAES = FALSE; 150 | else if (encType == 0x01) 151 | isAES = TRUE; 152 | else 153 | goto stopParse; 154 | 155 | //TODO: none encrypting encrypted swipe 156 | 157 | //get encrypted section 158 | int trackLens_enc[3]; 159 | int encryptionBlockSize = (isAES ? 16 : 8); 160 | for (int i=0; i<3; i++) { 161 | trackLens_enc[i] = 162 | ceil( trackLens[i] / (double)encryptionBlockSize ) * encryptionBlockSize; 163 | } 164 | int trackLensSum_enc=0; 165 | idx = 10 + trackLensSum; 166 | for (int i=0; i<3; i++) { 167 | //skip if len is 0 or presence flag not set 168 | if ( trackLens_enc[i]==0 || !isBitSet(bytes[9],i) ) 169 | continue; 170 | CHECK_INDEX(idx + trackLens_enc[i]); 171 | tracks_enc[i] = [cardData subdataWithRange: NSMakeRange(idx, trackLens_enc[i])]; 172 | idx += trackLens_enc[i]; 173 | trackLensSum_enc += trackLens_enc[i]; 174 | } 175 | 176 | //get KSN 177 | if ( (isBitSet(bytes[9], 7) ) && 178 | (isBitSet(bytes[9], 0)|| 179 | isBitSet(bytes[9], 1)|| 180 | isBitSet(bytes[9], 2) ) ) 181 | { 182 | idx = (int)(len-3-10); 183 | if (idx < 10 + trackLensSum + trackLensSum_enc) 184 | goto stopParse; 185 | ksn = [cardData subdataWithRange: NSMakeRange(idx, 10)]; 186 | } 187 | 188 | //get serial number 189 | if ( isBitSet(bytes[8], 7) ) { 190 | idx = (int)len-3-10 - (ksn ? 10 : 0); 191 | if (idx < 10 + trackLensSum + trackLensSum_enc) 192 | goto stopParse; 193 | serialNumber = [cardData subdataWithRange: NSMakeRange(idx, 10)]; 194 | } 195 | 196 | //all checks and parsing succeeded 197 | isSwipeDataValid = TRUE; 198 | 199 | #undef CHECK_INDEX 200 | } 201 | stopParse: 202 | 203 | //save result 204 | self->_isValid = isSwipeDataValid; 205 | self->_isAesEncrypted = isAES; 206 | self->_track1 = tracks[0]; 207 | self->_track2 = tracks[1]; 208 | self->_track3 = tracks[2]; 209 | self->_track1_encrypted = tracks_enc[0]; 210 | self->_track2_encrypted = tracks_enc[1]; 211 | self->_track3_encrypted = tracks_enc[2]; 212 | self->_serialNumber = serialNumber; 213 | self->_KSN = ksn; 214 | } 215 | 216 | -(void) verifyAndParse_unencrypted:(NSData*) cardData { 217 | /* 218 | Unencrypted swipe is the concatenation of one or more tracks (as listed below), 219 | then ended by a "\x0D". 220 | Track formats (in regular expression): 221 | ISO_1: "[\x25][^\x3F]+[\x3F]" 222 | ISO_2: "[\x3B][^\x3F]+[\x3F]" 223 | JIS : "[\x7F][^\x7F]+[\x7F]" 224 | */ 225 | 226 | BOOL isSwipeDataValid = FALSE; 227 | 228 | //shorthand 229 | const UInt8 *bytes= cardData.bytes; 230 | const NSUInteger len = cardData.length; 231 | 232 | if (bytes[len-1] == '\x0D') { 233 | isSwipeDataValid = YES; 234 | } 235 | 236 | //save result 237 | self->_isValid = isSwipeDataValid; 238 | } 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /ios/uniMag-SDK/uniMag.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2010-2016 ID TECH. All rights reserved. 2 | */ 3 | 4 | #import 5 | 6 | //Versioning 7 | #define UMSDK_VERSION @"7.20" 8 | #define UMSDK_CUSTOMIZATION 0 9 | 10 | //Notification identifiers used with NSNotificationCenter 11 | //physical attachment related 12 | #define uniMagAttachmentNotification @"uniMagAttachmentNotification" 13 | #define uniMagDetachmentNotification @"uniMagDetachmentNotification" 14 | //connection related 15 | #define uniMagInsufficientPowerNotification @"uniMagInsufficientPowerNotification" 16 | #define uniMagMonoAudioErrorNotification @"uniMagMonoAudioErrorNotification" 17 | #define uniMagPoweringNotification @"uniMagPoweringNotification" 18 | #define uniMagTimeoutNotification @"uniMagTimeoutNotification" 19 | #define uniMagDidConnectNotification @"uniMagDidConnectNotification" 20 | #define uniMagDidDisconnectNotification @"uniMagDidDisconnectNotification" 21 | //swipe related 22 | #define uniMagSwipeNotification @"uniMagSwipeNotification" 23 | #define uniMagTimeoutSwipeNotification @"uniMagTimeoutSwipe" 24 | #define uniMagDataProcessingNotification @"uniMagDataProcessingNotification" 25 | #define uniMagInvalidSwipeNotification @"uniMagInvalidSwipeNotification" 26 | #define uniMagDidReceiveDataNotification @"uniMagDidReceiveDataNotification" 27 | //command related 28 | #define uniMagCmdSendingNotification @"uniMagCmdSendingNotification" 29 | #define uniMagCommandTimeoutNotification @"uniMagCommandTimeout" 30 | #define uniMagDidReceiveCmdNotification @"uniMagDidReceiveCmdNotification" 31 | //misc 32 | #define uniMagSystemMessageNotification @"uniMagSystemMessageNotification" 33 | 34 | //Reader types 35 | typedef enum { 36 | UMREADER_UNKNOWN, 37 | UMREADER_UNIMAG_ORIGINAL, 38 | UMREADER_UNIMAG_PRO, 39 | UMREADER_UNIMAG_II, 40 | UMREADER_SHUTTLE, 41 | } UmReader; 42 | 43 | static inline NSString* UmReader_lookup(UmReader c) { 44 | switch (c) { 45 | case UMREADER_UNKNOWN : return @"Unknown"; 46 | case UMREADER_UNIMAG_ORIGINAL: return @"UniMag (original)"; 47 | case UMREADER_UNIMAG_PRO : return @"UniMag Pro"; 48 | case UMREADER_UNIMAG_II : return @"UniMag II"; 49 | case UMREADER_SHUTTLE : return @"Shuttle"; 50 | default: return @""; 51 | } 52 | } 53 | 54 | //SDK async task types 55 | typedef enum { 56 | UMTASK_NONE, //no async task running. SDK idle. 57 | UMTASK_CONNECT, //connection task 58 | UMTASK_SWIPE, //swipe task 59 | UMTASK_CMD, //command task 60 | UMTASK_FW_UPDATE, //firmware update task 61 | } UmTask; 62 | 63 | //async task methods return value 64 | //Description |Applicable task 65 | // |Connect|Swipe|Cmd|Update 66 | typedef enum { //--------------------------------------------+-------+-----+---+------ 67 | UMRET_SUCCESS, //no error, beginning task | * | * | * | * 68 | UMRET_NO_READER, //no reader attached | * | * | * | * 69 | UMRET_SDK_BUSY, //SDK is doing another task | * | * | * | * 70 | UMRET_MONO_AUDIO, //mono audio is enabled | * | | * | 71 | UMRET_ALREADY_CONNECTED,//did connection already | * | | | 72 | UMRET_LOW_VOLUME, //audio volume is too low | * | | | 73 | UMRET_NOT_CONNECTED, //did not do connection | | * | | 74 | UMRET_NOT_APPLICABLE, //operation not applicable to the reader type | | | * | 75 | UMRET_INVALID_ARG, //invalid argument passed to API | | | * | 76 | UMRET_UF_INVALID_STR, //UF wrong string format | | | | * 77 | UMRET_UF_NO_FILE, //UF file not found | | | | * 78 | UMRET_UF_INVALID_FILE, //UF wrong file format | | | | * 79 | } UmRet; 80 | 81 | static inline NSString* UmRet_lookup(UmRet c) { 82 | #define URLOOK(a) case a: return @#a; 83 | switch (c) { 84 | URLOOK(UMRET_SUCCESS ) 85 | URLOOK(UMRET_NO_READER ) 86 | URLOOK(UMRET_SDK_BUSY ) 87 | URLOOK(UMRET_MONO_AUDIO ) 88 | URLOOK(UMRET_ALREADY_CONNECTED) 89 | URLOOK(UMRET_LOW_VOLUME ) 90 | URLOOK(UMRET_NOT_CONNECTED ) 91 | URLOOK(UMRET_NOT_APPLICABLE ) 92 | URLOOK(UMRET_INVALID_ARG ) 93 | URLOOK(UMRET_UF_INVALID_STR ) 94 | URLOOK(UMRET_UF_NO_FILE ) 95 | URLOOK(UMRET_UF_INVALID_FILE ) 96 | default: return @""; 97 | } 98 | #undef URLOOK 99 | } 100 | 101 | //updateFirmware: codes return from notifications identifying their type 102 | typedef enum { 103 | UMUFCODE_SENDING_BLOCK=21, 104 | UMUFCODE_VERIFYING_CHECKSUM=30, 105 | UMUFCODE_RESENDING_BLOCK=40, 106 | UMUFCODE_FAILED_TO_ENTER_BOOTLOADER_MODE=303, 107 | UMUFCODE_FAILED_TO_SEND_BLOCK=305, 108 | UMUFCODE_FAILED_TO_VERIFY_CHECKSUM=306, 109 | UMUFCODE_CANCELED=307, 110 | } UmUfCode; 111 | 112 | //updateFirmware: dict key for block number from applicable notifications 113 | #define UmUfBlockNumberKey @"block_num" 114 | 115 | //tag used by SDK internally when logging 116 | // look for NSLog entries with these tags 117 | #define UMLOG_ERROR @"[UM Error] " 118 | #define UMLOG_WARNING @"[UM Warning] " 119 | #define UMLOG_INFO @"[UM Info] " 120 | 121 | 122 | @interface uniMag : NSObject 123 | 124 | //version 125 | +(NSString*) SDK_version; 126 | 127 | //status 128 | -(BOOL) isReaderAttached; 129 | -(BOOL) getConnectionStatus; 130 | -(UmTask) getRunningTask; 131 | -(float) getVolumeLevel; 132 | 133 | //config 134 | @property (nonatomic) UmReader readerType; 135 | -(void) setAutoConnect:(BOOL)autoConnect; 136 | -(BOOL) setSwipeTimeoutDuration:(NSInteger) seconds; 137 | -(void) setAutoAdjustVolume:(BOOL) b; 138 | -(void) setDeferredActivateAudioSession:(BOOL) b; 139 | 140 | //task 141 | -(void) cancelTask; 142 | 143 | //connect 144 | -(UmRet) startUniMag:(BOOL)start; 145 | 146 | //swipe 147 | -(UmRet) requestSwipe; 148 | -(NSData*) getFlagByte; 149 | 150 | //commands 151 | -(UmRet) sendCommandGetVersion; 152 | -(UmRet) sendCommandGetSettings; 153 | -(UmRet) sendCommandEnableTDES; 154 | -(UmRet) sendCommandEnableAES; 155 | -(UmRet) sendCommandDefaultGeneralSettings; 156 | -(UmRet) sendCommandGetSerialNumber; 157 | -(UmRet) sendCommandGetNextKSN; 158 | -(UmRet) sendCommandEnableErrNotification; 159 | -(UmRet) sendCommandDisableErrNotification; 160 | -(UmRet) sendCommandEnableExpDate; 161 | -(UmRet) sendCommandDisableExpDate; 162 | -(UmRet) sendCommandEnableForceEncryption; 163 | -(UmRet) sendCommandDisableForceEncryption; 164 | -(UmRet) sendCommandSetPrePAN: (NSInteger) prePAN; 165 | -(UmRet) sendCommandClearBuffer; 166 | -(UmRet) sendCommandResetBaudRate; 167 | -(UmRet) sendCommandCustom:(NSData *) cmd; 168 | 169 | // firmware updating 170 | -(UmRet) getAuthentication; 171 | -(BOOL) setFirmwareFile:(NSString*) location; 172 | -(UmRet) updateFirmware: (NSString*) encrytedBytes; 173 | -(UmRet) updateFirmware2:(NSString*) string withFile:(NSString*) path; 174 | 175 | // troubleshooting 176 | +(void) enableLogging:(BOOL) enable; 177 | -(NSData*) getWave; 178 | -(BOOL) setWavePath:(NSString*) path; 179 | 180 | //deprecated 181 | // This API now does nothing 182 | -(void) autoDetect:(BOOL)autoDetect; 183 | // Equivalent to '-setAutoConnect: ! prompt' 184 | -(void) promptForConnection:(BOOL)prompt; 185 | // Equivalent to '-startUniMag: proceedPowerUp' 186 | -(UmRet) proceedPoweringUp:(BOOL) proceedPowerUp; 187 | // Equivalent to '-startUniMag:FALSE' 188 | -(void) closeConnection; 189 | // Equivalent to '-cancelTask' 190 | -(void) cancelSwipe; 191 | // It is no longer possible to change command timeout 192 | -(BOOL) setCmdTimeoutDuration:(NSInteger) seconds; 193 | 194 | @end 195 | 196 | -------------------------------------------------------------------------------- /ios/uniMag-SDK/version.txt: -------------------------------------------------------------------------------- 1 | UniMag SDK 7.20 2 | 3 | For UniMag Original, Pro, II, and Shuttle MSR audio jack readers 4 | 5 | From 80110802-025 UniMag II iOS SDK IDTech v7.20 A 040516.zip 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-idtech-msr-audio", 3 | "version": "0.0.4", 4 | "main": "index.js", 5 | "author": "Peace Chen", 6 | "private": true, 7 | "scripts": { 8 | "start": "node node_modules/react-native/local-cli/cli.js start" 9 | }, 10 | "devDependencies": { 11 | "react": "*", 12 | "react-native": "*" 13 | }, 14 | "dependencies": { 15 | } 16 | } 17 | --------------------------------------------------------------------------------