I have made a class in Swift 5.0 that will use the Network module and identify the interface type currently used by the user.
import UIKit
import Network
@objc public class NetworkStrength: NSObject {
let shared = NetworkStrength()
var startTime = CFAbsoluteTime()
var stopTime = CFAbsoluteTime()
let monitor = NWPathMonitor()
@objc public var interfaceType = "No Interface connected"
@objc public func startMonitoring() {
let queue = DispatchQueue.global(qos: .background)
monitor.start(queue: queue)
monitor.pathUpdateHandler = { path in
if path.status == .satisfied {
print("Connected...")
let isCellular: Bool = path.usesInterfaceType(.cellular)
let isWifi: Bool = path.usesInterfaceType(.wifi)
let isEthernet: Bool = path.usesInterfaceType(.wiredEthernet)
let isOther: Bool = path.usesInterfaceType(.other)
let isLoopback: Bool = path.usesInterfaceType(.loopback)
if isCellular {
self.interfaceType = "Cellular"
}else if isWifi {
self.interfaceType = "Wifi"
}else if isEthernet {
self.interfaceType = "Wired Ethernet"
}else if isLoopback {
self.interfaceType = "Loopback"
}else if isOther{
self.interfaceType = "Other (Virtual or other undermined network)"
}else {
self.interfaceType = "No interface connected"
}
print("Interface Type => \(self.interfaceType)")
}
else if path.status == .requiresConnection || path.status == .unsatisfied {
print("Connection not available. Please connect to the internet.")
}
}
}
@objc public func stopMonitoring() {
monitor.cancel()
}
}
I have been asked to make a Unity iOS plugin where this code can be used in Unity by calling NetworkStrength.startMonitor() or NetworkStrength.interfaceType. The class is called NetworkStrength as it does have a custom speed test which I can't include because the code will become too big.
I do not have any experience using Objective C. But I have tried the following solutions.
Using these I have created an iOS framework project which has the files
NetworkStrength.swift // which is shown above
NetworkStrength.mm
#import <UIKit/UIKit.h>
#import <NetworkStrength/NetworkStrength-Swift.h>
#pragma mark - C interface
extern "C" {
void _startMonitoring() {
[[NetworkStrength shared] startMonitoring];
}
void _stopMonitoring() {
[[NetworkStrength shared] stopMonitoring];
}
char* _returnInterfaceType() {
NSString *returnString = [[NetworkStrength shared] interfaceType];
char* cStringCopy(const char* string);
return cStringCopy([returnString UTF8String]);
}
}
char* cStringCopy(const char* string){
if (string == NULL){
return NULL;
}
char* res = (char*)malloc(strlen(string)+1);
strcpy(res, string);
return res;
}
and
NetworkStrength.h as suggested in this link apple documentation which contains
@class NetworkStrength;
and setting Defines Module to Yes. I built the project and there were no errors.
So, I went ahead and created a new unity project housing all the above files inside Assets/Plugins/iOS/NetworkStrength/Source. Just like the blog said I created a NetworkStrength.cs file containing the following code.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class NetworkStrength : MonoBehaviour {
#region Declare external C interface
#if UNITY_IOS && !UNITY_EDITOR
[DllImport("__Internal")]
private static extern void _startMonitoring();
[DllImport("__Internal")]
private static extern void _stopMonitoring();
[DllImport("__Internal")]
private static extern void _returnInterfaceType();
#endif
#endregion
#region Wrapped methods and properties
public static void StartMonitoring() {
#if UNITY_IOS && !UNITY_EDITOR
_startMonitoring();
#endif
}
public static void StopMonitoring() {
#if UNITY_IOS && !UNITY_EDITOR
_stopMonitoring();
#endif
}
public static void ReturnInterfaceType() {
#if UNITY_IOS && !UNITY_EDITOR
_returnInterfaceType();
#endif
}
#endregion
#region Singleton implementation
private static NetworkStrength _instance;
public static NetworkStrength Instance
{
get
{
if (_instance == null)
{
var obj = new GameObject("NetworkStrength");
_instance = obj.AddComponent<NetworkStrength>();
}
return _instance;
}
}
private void Awake()
{
if (_instance != null)
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
}
#endregion
}
and added SwiftPostProcessor.cs to Assets/Plugins/iOS/NetworkStrength/Editor containing the following code.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Diagnostics;
using System.IO;
using System.Linq;
public static class SwiftPostProcess {
[PostProcessBuild]
public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
{
if (buildTarget == BuildTarget.iOS)
{
var projPath = buildPath + "/Unity-Iphone.xcodeproj/project.pbxproj";
var proj = new PBXProject();
proj.ReadFromFile(projPath);
var targetGuid = proj.GetUnityFrameworkTargetGuid() ;
//// Configure build settings
proj.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
proj.SetBuildProperty(targetGuid, "SWIFT_OBJC_BRIDGING_HEADER", "Libraries/Plugins/iOS/NetworkStrength/Source/NetworkStrength.h");
proj.SetBuildProperty(targetGuid, "SWIFT_OBJC_INTERFACE_HEADER_NAME", "NetworkStrength-Swift.h");
proj.AddBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");
proj.WriteToFile(projPath);
}
}
}
Having made this I built the project to see if there are any errors. The first error I got was
'NetworkStrength/NetworkStrength-Swift.h' file not found. I tried various solutions but I kept getting the same error every time. I can't seem to solve this issue. Please help me solve this issue.
PS. I tried NetworkStrength-Bridging-Header.h just like what the blog said but I kept getting the error: using bridging headers with framework targets is unsupported. I followed what was suggested in this solution.