├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── android
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── bebnev
│ ├── RNUserAgentModule.java
│ └── RNUserAgentPackage.java
├── index.d.ts
├── index.js
├── ios
├── RNUserAgent.h
├── RNUserAgent.m
└── RNUserAgent.xcodeproj
│ └── project.pbxproj
├── package.json
└── react-native-user-agent.podspec
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
47 | example/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Anton Bebnev
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # React Native User Agent
3 |
4 | ## Platforms Supported
5 |
6 | - [x] iOS
7 | - [x] Android
8 |
9 | ## Getting Started Guide
10 |
11 | 1. Add react-native-user-agent to your dependencies
12 |
13 | ```sh
14 | yarn add react-native-user-agent
15 | ```
16 |
17 | or, for npm use
18 |
19 | ```sh
20 | npm install react-native-user-agent --save
21 | ```
22 |
23 | 2. Link native dependencies
24 |
25 | 2.1 **react-native >= 0.60**
26 |
27 | Autolinking will take care of the link step, but for iOS, don't forget to run `pod install` in `ios/` folder
28 |
29 | If you haven't set up cocoapods yet, please refer to [that article](https://engineering.brigad.co/demystifying-react-native-modules-linking-ae6c017a6b4a)
30 |
31 | 2.2 **react-native < 0.60**
32 |
33 | You have to call `link` command manualy:
34 |
35 | ```sh
36 | react-native link react-native-user-agent
37 | ```
38 |
39 | *For manual linking*, please refer to:
40 | - [that article](https://engineering.brigad.co/demystifying-react-native-modules-linking-964399ec731b) for Android
41 | - [react-native own tutorial](https://facebook.github.io/react-native/docs/linking-libraries-ios) for iOS
42 |
43 | ## Usage
44 |
45 | ```javascript
46 | import UserAgent from 'react-native-user-agent';
47 |
48 | UserAgent.getUserAgent(); //synchronous
49 |
50 | UserAgent.getWebViewUserAgent() //asynchronous
51 | .then(ua => {})
52 | .catch(e => {})
53 | ```
54 |
55 | ### Examples:
56 |
57 | | System | User-Agent | WebView User-Agent |
58 | | ------ | ---------- | ------------------ |
59 | | iOS | application-name/1.6.4.176 CFNetwork/897.15 Darwin/17.5.0 (iPhone/6s iOS/11.3) | Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E217 |
60 | | Android | application-name/1.6.7.42 Dalvik/2.1.0 (Linux; U; Android 5.1.1; Android SDK built for x86 Build/LMY48X) | Mozilla/5.0 (Linux; Android 5.1.1; Android SDK built for x86 Build/LMY48X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 |
61 |
62 | Additionally module returns a set of constants, that are used in user agent string building.
63 |
64 | For iOS:
65 | - systemName
66 | - systemVersion
67 | - applicationName
68 | - applicationVersion
69 | - buildNumber
70 | - darwinVersion
71 | - cfnetworkVersion
72 | - deviceName **deprecated**
73 | - modelName
74 |
75 | For Android:
76 | - systemName
77 | - systemVersion
78 | - applicationName
79 | - applicationVersion
80 | - buildNumber
81 |
82 | ## Versioning
83 |
84 | **Breaking History:**
85 | - [2.3.1](https://github.com/bebnev/react-native-user-agent/releases/tag/v2.3.1)
86 | - fix android gradle script
87 | - [2.3.0](https://github.com/bebnev/react-native-user-agent/releases/tag/v2.3.0)
88 | - unification for ios device names
89 | - fix android gradle script
90 | - add types definition
91 | - [2.1.0](https://github.com/bebnev/react-native-user-agent/releases/tag/v2.1.0) - support for tvos
92 | - [2.0.0](https://github.com/bebnev/react-native-user-agent/releases/tag/v2.0.0) - supports [autolinking](https://github.com/react-native-community/cli/blob/master/docs/autolinking.md), native code refactoring, removes UIWebView, `getWebViewUserAgent()` returns promise
93 | - [1.0.6](https://github.com/bebnev/react-native-user-agent/releases/tag/v1.0.6) - First release
94 |
95 | ## License
96 |
97 | [MIT](LICENSE). Copyright (c) 2018 Anton Bebnev.
98 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 | def buildGradleVersion = ext.has('buildGradlePluginVersion') ? ext.get('buildGradlePluginVersion') : '3.5.3'
7 |
8 | dependencies {
9 | classpath "com.android.tools.build:gradle:$buildGradleVersion"
10 | }
11 | }
12 |
13 | def safeExtGet(prop, fallback) {
14 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
15 | }
16 |
17 | apply plugin: 'com.android.library'
18 |
19 | android {
20 | compileSdkVersion safeExtGet('compileSdkVersion', 28)
21 | buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
22 |
23 | defaultConfig {
24 | minSdkVersion safeExtGet('minSdkVersion', 16)
25 | targetSdkVersion safeExtGet('targetSdkVersion', 28)
26 | versionCode 1
27 | versionName "1.0"
28 | }
29 |
30 | lintOptions {
31 | abortOnError false
32 | }
33 | }
34 |
35 | repositories {
36 | google()
37 | mavenCentral()
38 | }
39 |
40 | dependencies {
41 | implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
42 | }
43 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/android/src/main/java/com/bebnev/RNUserAgentModule.java:
--------------------------------------------------------------------------------
1 | package com.bebnev;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 | import android.content.pm.PackageManager;
6 | import android.content.pm.PackageInfo;
7 | import android.util.Log;
8 | import android.os.Build;
9 | import android.webkit.WebSettings;
10 | import android.webkit.WebView;
11 |
12 | import com.facebook.react.bridge.Arguments;
13 | import com.facebook.react.bridge.Promise;
14 | import com.facebook.react.bridge.ReactApplicationContext;
15 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
16 | import com.facebook.react.bridge.ReactMethod;
17 | import com.facebook.react.bridge.WritableArray;
18 | import com.facebook.react.module.annotations.ReactModule;
19 | import com.facebook.react.bridge.UiThreadUtil;
20 |
21 | import java.util.ArrayList;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 | import java.lang.Runtime;
25 |
26 | @ReactModule(name = RNUserAgentModule.NAME)
27 | public class RNUserAgentModule extends ReactContextBaseJavaModule {
28 | public static final String NAME = "RNUserAgent";
29 |
30 | public RNUserAgentModule(ReactApplicationContext reactContext) {
31 | super(reactContext);
32 | }
33 |
34 | @Override
35 | public String getName() {
36 | return NAME;
37 | }
38 |
39 | protected String getUserAgent() {
40 | try {
41 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
42 | return WebSettings.getDefaultUserAgent(getReactApplicationContext());
43 | } else {
44 | return System.getProperty("http.agent");
45 | }
46 | } catch (RuntimeException e) {
47 | return System.getProperty("http.agent");
48 | }
49 | }
50 |
51 | @ReactMethod
52 | protected void getWebViewUserAgent(final Promise p) {
53 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
54 | p.resolve(WebSettings.getDefaultUserAgent(getReactApplicationContext()));
55 | }
56 |
57 | UiThreadUtil.runOnUiThread(
58 | new Runnable() {
59 | @Override
60 | public void run() {
61 | p.resolve(new WebView(getReactApplicationContext()).getSettings().getUserAgentString());
62 | }
63 | }
64 | );
65 | }
66 |
67 | private PackageInfo getPackageInfo() throws Exception {
68 | return getReactApplicationContext().getPackageManager().getPackageInfo(getReactApplicationContext().getPackageName(), 0);
69 | }
70 |
71 | @Override
72 | public Map getConstants() {
73 | String packageName = getReactApplicationContext().getPackageName();
74 | String shortPackageName = packageName.substring(packageName.lastIndexOf(".") + 1);
75 | String applicationVersion = "";
76 | String applicationName = "";
77 | String buildNumber = "";
78 | String userAgent = "";
79 |
80 | try {
81 | applicationName = getReactApplicationContext().getApplicationInfo().loadLabel(getReactApplicationContext().getPackageManager()).toString();
82 | applicationVersion = getPackageInfo().versionName;
83 | buildNumber = Integer.toString(getPackageInfo().versionCode);
84 | userAgent = shortPackageName + '/' + applicationVersion + '.' + buildNumber.toString() + ' ' + this.getUserAgent();
85 | } catch(Exception e) {
86 | e.printStackTrace();
87 | }
88 |
89 | HashMap constants = new HashMap();
90 |
91 | constants.put("systemName", "Android");
92 | constants.put("systemVersion", Build.VERSION.RELEASE);
93 | constants.put("packageName", packageName);
94 | constants.put("shortPackageName", shortPackageName);
95 | constants.put("applicationName", applicationName);
96 | constants.put("applicationVersion", applicationVersion);
97 | constants.put("buildNumber", buildNumber);
98 | constants.put("userAgent", userAgent);
99 |
100 | return constants;
101 | }
102 | }
--------------------------------------------------------------------------------
/android/src/main/java/com/bebnev/RNUserAgentPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.bebnev;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 | import com.facebook.react.bridge.JavaScriptModule;
13 |
14 | public class RNUserAgentPackage implements ReactPackage {
15 | @Override
16 | public List createNativeModules(ReactApplicationContext reactContext) {
17 | return Arrays.asList(new RNUserAgentModule(reactContext));
18 | }
19 |
20 | @Override
21 | public List createViewManagers(ReactApplicationContext reactContext) {
22 | return Collections.emptyList();
23 | }
24 | }
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | export function getUserAgent(): string;
2 | export function getWebViewUserAgent(): Promise;
3 |
4 | // Android + iOS
5 | export const systemName: string;
6 | export const systemVersion: string;
7 | export const applicationName: string;
8 | export const applicationVersion: string;
9 | export const buildNumber: string;
10 |
11 | // iOS only
12 | export const darwinVersion: string|undefined;
13 | export const cfnetworkVersion: string|undefined;
14 | export const modelName: string|undefined;
15 |
16 | /**
17 | * @deprecated
18 | */
19 | export const deviceName: string|undefined;
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { NativeModules } from 'react-native';
3 |
4 | const { RNUserAgent } = NativeModules;
5 |
6 | module.exports = {
7 | ...RNUserAgent,
8 | getUserAgent: () => {
9 | return RNUserAgent.userAgent;
10 | }
11 | };
12 |
13 |
--------------------------------------------------------------------------------
/ios/RNUserAgent.h:
--------------------------------------------------------------------------------
1 |
2 | #import
3 |
4 | #if __has_include("RCTBridgeModule.h")
5 | #import "RCTBridgeModule.h"
6 | #else
7 | #import
8 | #endif
9 |
10 | @interface RNUserAgent : NSObject
11 | @end
12 |
--------------------------------------------------------------------------------
/ios/RNUserAgent.m:
--------------------------------------------------------------------------------
1 | //
2 | // UserAgent.m
3 | // lkfl
4 | //
5 | // Created by Anton Bebnev on 05.07.2018.
6 | #import "RNUserAgent.h"
7 | #if !(TARGET_OS_TV)
8 | #import
9 | #endif
10 |
11 | @implementation RNUserAgent
12 | {
13 | #if !(TARGET_OS_TV)
14 | WKWebView *webView;
15 | #endif
16 | }
17 |
18 | RCT_EXPORT_MODULE(RNUserAgent);
19 |
20 | + (BOOL)requiresMainQueueSetup
21 | {
22 | return YES;
23 | }
24 |
25 | //eg. Darwin/16.3.0
26 | - (NSString *)getDarwinVersion
27 | {
28 | struct utsname u;
29 | (void) uname(&u);
30 | return [NSString stringWithUTF8String:u.release];
31 | }
32 |
33 | //eg. iPhone 11 Pro Max
34 | - (NSString *)getModel
35 | {
36 | struct utsname systemInfo;
37 | uname(&systemInfo);
38 |
39 | NSString* deviceId = [NSString stringWithUTF8String:systemInfo.machine];
40 |
41 | if ([deviceId isEqualToString:@"i386"] || [deviceId isEqualToString:@"x86_64"] ) {
42 | deviceId = [NSString stringWithFormat:@"%s", getenv("SIMULATOR_MODEL_IDENTIFIER")];
43 | }
44 |
45 | static NSDictionary* deviceNames = nil;
46 |
47 | if (!deviceNames) {
48 |
49 | deviceNames = @{@"iPad1,1" :@"iPad", // (Original)
50 | @"iPad2,1" :@"iPad/2",
51 | @"iPad2,2" :@"iPad/2",
52 | @"iPad2,3" :@"iPad/2",
53 | @"iPad2,4" :@"iPad/2",
54 | @"iPad3,1" :@"iPad", // (3rd Generation)
55 | @"iPad3,2" :@"iPad", // (3rd Generation)
56 | @"iPad3,3" :@"iPad", // (3rd Generation)
57 | @"iPad3,4" :@"iPad", // (4th Generation)
58 | @"iPad3,5" :@"iPad", // (4th Generation)
59 | @"iPad3,6" :@"iPad", // (4th Generation)
60 | @"iPad2,5" :@"iPad/Mini", // (Original)
61 | @"iPad2,6" :@"iPad/Mini", // (Original)
62 | @"iPad2,7" :@"iPad/Mini", // (Original)
63 | @"iPad4,1" :@"iPad/Air", // 5th Generation iPad (iPad Air) - Wifi
64 | @"iPad4,2" :@"iPad/Air", // 5th Generation iPad (iPad Air) - Cellular
65 | @"iPad4,3" :@"iPad/Air", // 5th Generation iPad (iPad Air)
66 | @"iPad4,4" :@"iPad/Mini_2", // (2nd Generation iPad Mini - Wifi)
67 | @"iPad4,5" :@"iPad/Mini_2", // (2nd Generation iPad Mini - Cellular)
68 | @"iPad4,6" :@"iPad/Mini_2", // (2nd Generation iPad Mini)
69 | @"iPad4,7" :@"iPad/Mini_3", // (3rd Generation iPad Mini)
70 | @"iPad4,8" :@"iPad/Mini_3", // (3rd Generation iPad Mini)
71 | @"iPad4,9" :@"iPad/Mini_3", // (3rd Generation iPad Mini)
72 | @"iPad5,1" :@"iPad/Mini_4", // (4th Generation iPad Mini)
73 | @"iPad5,2" :@"iPad/Mini_4", // (4th Generation iPad Mini)
74 | @"iPad5,3" :@"iPad/Air_2", // 6th Generation iPad (iPad/Air_2)
75 | @"iPad5,4" :@"iPad/Air_2", // 6th Generation iPad (iPad/Air_2)
76 | @"iPad6,3" :@"iPad/Pro_9.7-inch",// iPad/Pro_9.7-inch
77 | @"iPad6,4" :@"iPad/Pro_9.7-inch",// iPad/Pro_9.7-inch
78 | @"iPad6,7" :@"iPad/Pro_12.9-inch",// iPad/Pro_12.9-inch
79 | @"iPad6,8" :@"iPad/Pro_12.9-inch",// iPad/Pro_12.9-inch
80 | @"iPad7,1" :@"iPad/Pro_12.9-inch",// 2nd Generation iPad Pro 12.5-inch - Wifi
81 | @"iPad7,2" :@"iPad/Pro_12.9-inch",// 2nd Generation iPad Pro 12.5-inch - Cellular
82 | @"iPad7,3" :@"iPad/Pro_10.5-inch",// iPad/Pro_10.5-inch - Wifi
83 | @"iPad7,4" :@"iPad/Pro_10.5-inch",// iPad/Pro_10.5-inch - Cellular
84 | @"iPad7,5": @"iPad (6th generation)", // iPad (6th generation) - Wifi
85 | @"iPad7,6": @"iPad (6th generation)", // iPad (6th generation) - Cellular
86 | @"iPad7,11": @"iPad (7th generation)", // iPad 10.2 inch (7th generation) - Wifi
87 | @"iPad7,12": @"iPad (7th generation)", // iPad 10.2 inch (7th generation) - Wifi + cellular
88 | @"iPad8,1": @"iPad Pro 11-inch (3rd generation)", // iPad Pro 11 inch (3rd generation) - Wifi
89 | @"iPad8,2": @"iPad Pro 11-inch (3rd generation)", // iPad Pro 11 inch (3rd generation) - 1TB - Wifi
90 | @"iPad8,3": @"iPad Pro 11-inch (3rd generation)", // iPad Pro 11 inch (3rd generation) - Wifi + cellular
91 | @"iPad8,4": @"iPad Pro 11-inch (3rd generation)", // iPad Pro 11 inch (3rd generation) - 1TB - Wifi + cellular
92 | @"iPad8,5": @"iPad Pro 12.9-inch (3rd generation)", // iPad Pro 12.9 inch (3rd generation) - Wifi
93 | @"iPad8,6": @"iPad Pro 12.9-inch (3rd generation)", // iPad Pro 12.9 inch (3rd generation) - 1TB - Wifi
94 | @"iPad8,7": @"iPad Pro 12.9-inch (3rd generation)", // iPad Pro 12.9 inch (3rd generation) - Wifi + cellular
95 | @"iPad8,8": @"iPad Pro 12.9-inch (3rd generation)", // iPad Pro 12.9 inch (3rd generation) - 1TB - Wifi + cellular
96 | @"iPad11,1": @"iPad Mini 5", // (5th Generation iPad Mini)
97 | @"iPad11,2": @"iPad Mini 5", // (5th Generation iPad Mini)
98 | @"iPad11,3": @"iPad Air (3rd generation)",
99 | @"iPad11,4": @"iPad Air (3rd generation)",
100 | @"iPad13,1": @"iPad Air (4th generation)",
101 | @"iPad13,2": @"iPad Air (4th generation)",
102 | @"iPhone1,1" :@"iPhone", // (Original)
103 | @"iPhone1,2" :@"iPhone/3G", // (3G)
104 | @"iPhone2,1" :@"iPhone/3GS", // (3GS)
105 | @"iPhone3,1" :@"iPhone/4", // (GSM)
106 | @"iPhone3,2" :@"iPhone/4", // iPhone 4
107 | @"iPhone3,3" :@"iPhone/4", // (CDMA/Verizon/Sprint)
108 | @"iPhone4,1" :@"iPhone/4S", //
109 | @"iPhone5,1" :@"iPhone/5", // (model A1428, AT&T/Canada)
110 | @"iPhone5,2" :@"iPhone/5", // (model A1429, everything else)
111 | @"iPhone5,3" :@"iPhone/5c", // (model A1456, A1532 | GSM)
112 | @"iPhone5,4" :@"iPhone/5c", // (model A1507, A1516, A1526 (China), A1529 | Global)
113 | @"iPhone6,1" :@"iPhone/5s", // (model A1433, A1533 | GSM)
114 | @"iPhone6,2" :@"iPhone/5s", // (model A1457, A1518, A1528 (China), A1530 | Global)
115 | @"iPhone7,1" :@"iPhone/6_Plus",
116 | @"iPhone7,2" :@"iPhone/6",
117 | @"iPhone8,1" :@"iPhone/6s",
118 | @"iPhone8,2" :@"iPhone/6s_Plus",
119 | @"iPhone8,4" :@"iPhone/SE",
120 | @"iPhone9,1" :@"iPhone/7", // (model A1660 | CDMA)
121 | @"iPhone9,3" :@"iPhone/7", // (model A1778 | Global)
122 | @"iPhone9,2" :@"iPhone/7_Plus", // (model A1661 | CDMA)
123 | @"iPhone9,4" :@"iPhone/7_Plus", // (model A1784 | Global)
124 | @"iPhone10,1":@"iPhone/8", // (model A1863, A1906, A1907)
125 | @"iPhone10,2":@"iPhone/8_Plus", // (model A1864, A1898, A1899)
126 | @"iPhone10,3":@"iPhone/X", // (model A1865, A1902)
127 | @"iPhone10,4":@"iPhone/8", // (model A1905)
128 | @"iPhone10,5":@"iPhone/8_Plus", // (model A1897)
129 | @"iPhone10,6":@"iPhone/X", // (model A1901)
130 | @"iPhone11,2": @"iPhone/XS", // (model A2097, A2098)
131 | @"iPhone11,4": @"iPhone/XS_Max", // (model A1921, A2103)
132 | @"iPhone11,6": @"iPhone/XS_Max", // (model A2104)
133 | @"iPhone11,8": @"iPhone/XR", // (model A1882, A1719, A2105)
134 | @"iPhone12,1": @"iPhone/11",
135 | @"iPhone12,3": @"iPhone/11_Pro",
136 | @"iPhone12,5": @"iPhone/11_Pro_Max",
137 | @"iPhone12,8": @"iPhone/SE", // (2nd Generation iPhone SE),
138 | @"iPhone13,1": @"iPhone/12_mini",
139 | @"iPhone13,2": @"iPhone/12",
140 | @"iPhone13,3": @"iPhone/12_Pro",
141 | @"iPhone13,4": @"iPhone/12_Pro_Max",
142 | @"iPhone14,4": @"iPhone/13_mini",
143 | @"iPhone14,5": @"iPhone/13",
144 | @"iPhone14,2": @"iPhone/13_Pro",
145 | @"iPhone14,3": @"iPhone/13_Pro_Max",
146 | @"AppleTV2,1":@"AppleTV", // Apple TV (2nd Generation)
147 | @"AppleTV3,1":@"AppleTV", // Apple TV (3rd Generation)
148 | @"AppleTV3,2":@"AppleTV", // Apple TV (3rd Generation - Rev A)
149 | @"AppleTV5,3":@"AppleTV", // Apple TV (4th Generation)
150 | @"AppleTV6,2":@"AppleTV_4K", // Apple TV 4K
151 | };
152 | }
153 |
154 | NSString* deviceName = [deviceNames valueForKey:deviceId];
155 |
156 | if (deviceName) {
157 | return deviceName;
158 | }
159 |
160 | if([deviceId hasPrefix:@"iPad"]) {
161 | return @"iPad";
162 | }
163 | else if([deviceId hasPrefix:@"iPhone"]){
164 | return @"iPhone";
165 | }
166 | else if([deviceId hasPrefix:@"AppleTV"]){
167 | return @"AppleTV";
168 | }
169 |
170 | return @"unknown";
171 | }
172 |
173 |
174 | - (NSString *)getAppName
175 | {
176 | return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"] ?: [NSNull null];
177 | }
178 |
179 | - (NSString *)getAppVersion
180 | {
181 | return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] ?: [NSNull null];
182 | }
183 |
184 | - (NSString *)getBuildNumber
185 | {
186 | return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] ?: [NSNull null];
187 | }
188 |
189 | - (NSString *)getCfnVersion
190 | {
191 | return [NSBundle bundleWithIdentifier:@"com.apple.CFNetwork"].infoDictionary[@"CFBundleShortVersionString"];
192 | }
193 |
194 | RCT_EXPORT_METHOD(getWebViewUserAgent:(RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock)reject)
195 | {
196 | #if TARGET_OS_TV
197 | reject(@"not_available_error", @"not available on tvOS", nil);
198 | #else
199 | __weak RNUserAgent *weakSelf = self;
200 | //__block WKWebView* webView = [[WKWebView alloc] init];
201 | dispatch_async(
202 | dispatch_get_main_queue(), ^{
203 | __strong RNUserAgent *strongSelf = weakSelf;
204 |
205 | if (strongSelf) {
206 | strongSelf->webView = [[WKWebView alloc] init];
207 |
208 | [strongSelf->webView evaluateJavaScript:@"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
209 | if (error) {
210 | reject(@"getWebViewUserAgentError", error.localizedDescription, error);
211 | return;
212 | }
213 |
214 | resolve([NSString stringWithFormat:@"%@", result]);
215 | strongSelf->webView = nil;
216 | }];
217 | }
218 | }
219 | );
220 | #endif
221 | }
222 |
223 | - (NSDictionary *)constantsToExport
224 | {
225 | UIDevice *currentDevice = [UIDevice currentDevice];
226 |
227 | NSString* appName = [self getAppName];
228 | NSString* appVersion = [self getAppVersion];
229 | NSString* buildNumber = [self getBuildNumber];
230 | NSString* darwinVersion = [self getDarwinVersion];
231 | NSString* cfnVersion = [self getCfnVersion];
232 | NSString* modelName = [self getModel];
233 |
234 | return @{
235 | @"systemName": currentDevice.systemName,
236 | @"systemVersion": currentDevice.systemVersion,
237 | @"applicationName": appName,
238 | @"applicationVersion": appVersion,
239 | @"buildNumber": buildNumber,
240 | @"darwinVersion": darwinVersion,
241 | @"cfnetworkVersion": cfnVersion,
242 | @"deviceName": modelName, //@deprecated
243 | @"modelName": modelName,
244 | @"userAgent": [NSString stringWithFormat:@"%@/%@.%@ CFNetwork/%@ Darwin/%@ (%@ %@/%@)", appName, appVersion, buildNumber, cfnVersion, darwinVersion, modelName, currentDevice.systemName, currentDevice.systemVersion]
245 | };
246 | }
247 |
248 | @end
249 |
--------------------------------------------------------------------------------
/ios/RNUserAgent.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B3E7B58A1CC2AC0600A0062D /* RNUserAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNUserAgent.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 134814201AA4EA6300B7C361 /* libRNUserAgent.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNUserAgent.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | B3E7B5881CC2AC0600A0062D /* RNUserAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNUserAgent.h; sourceTree = ""; };
28 | B3E7B5891CC2AC0600A0062D /* RNUserAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNUserAgent.m; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 134814211AA4EA7D00B7C361 /* Products */ = {
43 | isa = PBXGroup;
44 | children = (
45 | 134814201AA4EA6300B7C361 /* libRNUserAgent.a */,
46 | );
47 | name = Products;
48 | sourceTree = "";
49 | };
50 | 58B511D21A9E6C8500147676 = {
51 | isa = PBXGroup;
52 | children = (
53 | B3E7B5881CC2AC0600A0062D /* RNUserAgent.h */,
54 | B3E7B5891CC2AC0600A0062D /* RNUserAgent.m */,
55 | 134814211AA4EA7D00B7C361 /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXNativeTarget section */
62 | 58B511DA1A9E6C8500147676 /* RNUserAgent */ = {
63 | isa = PBXNativeTarget;
64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNUserAgent" */;
65 | buildPhases = (
66 | 58B511D71A9E6C8500147676 /* Sources */,
67 | 58B511D81A9E6C8500147676 /* Frameworks */,
68 | 58B511D91A9E6C8500147676 /* CopyFiles */,
69 | );
70 | buildRules = (
71 | );
72 | dependencies = (
73 | );
74 | name = RNUserAgent;
75 | productName = RCTDataManager;
76 | productReference = 134814201AA4EA6300B7C361 /* libRNUserAgent.a */;
77 | productType = "com.apple.product-type.library.static";
78 | };
79 | /* End PBXNativeTarget section */
80 |
81 | /* Begin PBXProject section */
82 | 58B511D31A9E6C8500147676 /* Project object */ = {
83 | isa = PBXProject;
84 | attributes = {
85 | LastUpgradeCheck = 0830;
86 | ORGANIZATIONNAME = Facebook;
87 | TargetAttributes = {
88 | 58B511DA1A9E6C8500147676 = {
89 | CreatedOnToolsVersion = 6.1.1;
90 | };
91 | };
92 | };
93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNUserAgent" */;
94 | compatibilityVersion = "Xcode 3.2";
95 | developmentRegion = English;
96 | hasScannedForEncodings = 0;
97 | knownRegions = (
98 | en,
99 | );
100 | mainGroup = 58B511D21A9E6C8500147676;
101 | productRefGroup = 58B511D21A9E6C8500147676;
102 | projectDirPath = "";
103 | projectRoot = "";
104 | targets = (
105 | 58B511DA1A9E6C8500147676 /* RNUserAgent */,
106 | );
107 | };
108 | /* End PBXProject section */
109 |
110 | /* Begin PBXSourcesBuildPhase section */
111 | 58B511D71A9E6C8500147676 /* Sources */ = {
112 | isa = PBXSourcesBuildPhase;
113 | buildActionMask = 2147483647;
114 | files = (
115 | B3E7B58A1CC2AC0600A0062D /* RNUserAgent.m in Sources */,
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXSourcesBuildPhase section */
120 |
121 | /* Begin XCBuildConfiguration section */
122 | 58B511ED1A9E6C8500147676 /* Debug */ = {
123 | isa = XCBuildConfiguration;
124 | buildSettings = {
125 | ALWAYS_SEARCH_USER_PATHS = NO;
126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
127 | CLANG_CXX_LIBRARY = "libc++";
128 | CLANG_ENABLE_MODULES = YES;
129 | CLANG_ENABLE_OBJC_ARC = YES;
130 | CLANG_WARN_BOOL_CONVERSION = YES;
131 | CLANG_WARN_CONSTANT_CONVERSION = YES;
132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
133 | CLANG_WARN_EMPTY_BODY = YES;
134 | CLANG_WARN_ENUM_CONVERSION = YES;
135 | CLANG_WARN_INFINITE_RECURSION = YES;
136 | CLANG_WARN_INT_CONVERSION = YES;
137 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
138 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
139 | CLANG_WARN_UNREACHABLE_CODE = YES;
140 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
141 | COPY_PHASE_STRIP = NO;
142 | ENABLE_STRICT_OBJC_MSGSEND = YES;
143 | ENABLE_TESTABILITY = YES;
144 | GCC_C_LANGUAGE_STANDARD = gnu99;
145 | GCC_DYNAMIC_NO_PIC = NO;
146 | GCC_NO_COMMON_BLOCKS = YES;
147 | GCC_OPTIMIZATION_LEVEL = 0;
148 | GCC_PREPROCESSOR_DEFINITIONS = (
149 | "DEBUG=1",
150 | "$(inherited)",
151 | );
152 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
153 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
154 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
155 | GCC_WARN_UNDECLARED_SELECTOR = YES;
156 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
157 | GCC_WARN_UNUSED_FUNCTION = YES;
158 | GCC_WARN_UNUSED_VARIABLE = YES;
159 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
160 | MTL_ENABLE_DEBUG_INFO = YES;
161 | ONLY_ACTIVE_ARCH = YES;
162 | SDKROOT = iphoneos;
163 | };
164 | name = Debug;
165 | };
166 | 58B511EE1A9E6C8500147676 /* Release */ = {
167 | isa = XCBuildConfiguration;
168 | buildSettings = {
169 | ALWAYS_SEARCH_USER_PATHS = NO;
170 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
171 | CLANG_CXX_LIBRARY = "libc++";
172 | CLANG_ENABLE_MODULES = YES;
173 | CLANG_ENABLE_OBJC_ARC = YES;
174 | CLANG_WARN_BOOL_CONVERSION = YES;
175 | CLANG_WARN_CONSTANT_CONVERSION = YES;
176 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
177 | CLANG_WARN_EMPTY_BODY = YES;
178 | CLANG_WARN_ENUM_CONVERSION = YES;
179 | CLANG_WARN_INFINITE_RECURSION = YES;
180 | CLANG_WARN_INT_CONVERSION = YES;
181 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
182 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
183 | CLANG_WARN_UNREACHABLE_CODE = YES;
184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
185 | COPY_PHASE_STRIP = YES;
186 | ENABLE_NS_ASSERTIONS = NO;
187 | ENABLE_STRICT_OBJC_MSGSEND = YES;
188 | GCC_C_LANGUAGE_STANDARD = gnu99;
189 | GCC_NO_COMMON_BLOCKS = YES;
190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
191 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
192 | GCC_WARN_UNDECLARED_SELECTOR = YES;
193 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
194 | GCC_WARN_UNUSED_FUNCTION = YES;
195 | GCC_WARN_UNUSED_VARIABLE = YES;
196 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
197 | MTL_ENABLE_DEBUG_INFO = NO;
198 | SDKROOT = iphoneos;
199 | VALIDATE_PRODUCT = YES;
200 | };
201 | name = Release;
202 | };
203 | 58B511F01A9E6C8500147676 /* Debug */ = {
204 | isa = XCBuildConfiguration;
205 | buildSettings = {
206 | HEADER_SEARCH_PATHS = (
207 | "$(inherited)",
208 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
209 | "$(SRCROOT)/../../../React/**",
210 | "$(SRCROOT)/../../react-native/React/**",
211 | );
212 | LIBRARY_SEARCH_PATHS = "$(inherited)";
213 | OTHER_LDFLAGS = "-ObjC";
214 | PRODUCT_NAME = RNUserAgent;
215 | SKIP_INSTALL = YES;
216 | };
217 | name = Debug;
218 | };
219 | 58B511F11A9E6C8500147676 /* Release */ = {
220 | isa = XCBuildConfiguration;
221 | buildSettings = {
222 | HEADER_SEARCH_PATHS = (
223 | "$(inherited)",
224 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
225 | "$(SRCROOT)/../../../React/**",
226 | "$(SRCROOT)/../../react-native/React/**",
227 | );
228 | LIBRARY_SEARCH_PATHS = "$(inherited)";
229 | OTHER_LDFLAGS = "-ObjC";
230 | PRODUCT_NAME = RNUserAgent;
231 | SKIP_INSTALL = YES;
232 | };
233 | name = Release;
234 | };
235 | /* End XCBuildConfiguration section */
236 |
237 | /* Begin XCConfigurationList section */
238 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNUserAgent" */ = {
239 | isa = XCConfigurationList;
240 | buildConfigurations = (
241 | 58B511ED1A9E6C8500147676 /* Debug */,
242 | 58B511EE1A9E6C8500147676 /* Release */,
243 | );
244 | defaultConfigurationIsVisible = 0;
245 | defaultConfigurationName = Release;
246 | };
247 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNUserAgent" */ = {
248 | isa = XCConfigurationList;
249 | buildConfigurations = (
250 | 58B511F01A9E6C8500147676 /* Debug */,
251 | 58B511F11A9E6C8500147676 /* Release */,
252 | );
253 | defaultConfigurationIsVisible = 0;
254 | defaultConfigurationName = Release;
255 | };
256 | /* End XCConfigurationList section */
257 | };
258 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
259 | }
260 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-user-agent",
3 | "version": "2.3.1",
4 | "description": "Library that helps you to get mobile application user agent and web view user agent strings.",
5 | "main": "index.js",
6 | "types": "index.d.ts",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/bebnev/react-native-user-agent.git"
10 | },
11 | "keywords": [
12 | "react-native",
13 | "user-agent",
14 | "user agent",
15 | "http",
16 | "webView",
17 | "httpUserAgent"
18 | ],
19 | "author": "Bebnev Anton ",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/bebnev/react-native-user-agent/issues"
23 | },
24 | "homepage": "https://github.com/bebnev/react-native-user-agent",
25 | "peerDependencies": {
26 | "react-native": "*"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/react-native-user-agent.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = package["name"]
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 | s.description = package["description"]
10 | s.license = package["license"]
11 |
12 | s.authors = package["author"]
13 | s.homepage = package["homepage"]
14 | s.platform = :ios, "9.0"
15 | s.ios.deployment_target = "9.0"
16 | s.tvos.deployment_target = "10.0"
17 |
18 | s.source = { :git => package["repository"]["url"], :tag => "v#{s.version}" }
19 | s.source_files = "ios/**/*.{h,m}"
20 |
21 | s.dependency "React"
22 |
23 | end
24 |
--------------------------------------------------------------------------------