[Unity]调用iOS(自己的插件)

        之前调用iOS的SDK代码都是将Unity导出XCode工程,再将iOS代码拷贝到XCode工程目录下,手动在CompileSources中添加。但在接入MSDK和米大师,嫌大厂的麻烦,自己写了一套自动配置Xcode工程的代码。感觉略微了解XCode的配置。

        在后续的对接中,大厂需要收集运营商和网络情况(Wifi/2G/3G/4G)这些数据,就尝试写个iOS的插件,减少手动操作的麻烦和出错概率。

        经过网上一番搜索和自己动手测试后,得出结论:只需要将.h和.m文件拷入到Plugins/iOS目录下,后续在XCode中就不需要管了,如下图:

        调用也跟之前接入SDK类似,先写个DllImport,然后就可以直接调用了,代码:

public class MobileUtility
{
    private static AndroidJavaObject m_apiInstance;
    private static AndroidJavaObject m_currentActivity;
    private static AndroidJavaObject m_assetManager;

    [DllImport("__Internal")]
    private static extern string iGetMobileCarrier();

    [DllImport("__Internal")]
    private static extern string iGetNetworkType();

    [DllImport("__Internal")]
    private static extern string iGetIDFA();

    [DllImport("__Internal")]
    private static extern float iGetNotchScreenSize();

    /// <summary>
    /// 获取安卓工具类实例
    /// </summary>
    /// <returns></returns>
    private static AndroidJavaObject GetApiInstance()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        if (null == m_apiInstance)
        {
            var apiClass = new AndroidJavaClass("com.zp.utility.api");

            m_apiInstance = apiClass.CallStatic<AndroidJavaObject>("instance");
        }
#endif
        return m_apiInstance;
    }

    /// <summary>
    /// 获取当前Activity
    /// </summary>
    /// <returns></returns>
    private static AndroidJavaObject GetCurrentActivity()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        if (null == m_currentActivity)
            m_currentActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
#endif
        return m_currentActivity;
    }

    /// <summary>
    /// 获取安卓的AssetManager,用于读取Unity中StreamingAsset中的文件
    /// </summary>
    /// <returns></returns>
    private static AndroidJavaObject GetAssetManager()
    {
#if UNITY_ANDROID && !UNITY_EDITOR
        if (null == m_assetManager)
        {
            var currentActivity = GetCurrentActivity();

            if(currentActivity != null)
                m_assetManager = currentActivity.Call<AndroidJavaObject>("getAssets");
        }
#endif
        return m_assetManager;
    }

    /// <summary>
    /// 获取手机imei
    /// </summary>
    /// <returns></returns>
    public static string GetIMEIOrIDFA()
    {
        string result = "";
#if UNITY_ANDROID && !UNITY_EDITOR
        var currentActivity = GetCurrentActivity();
        AndroidJavaClass contextClass = new AndroidJavaClass("android.content.Context");
        string TELEPHONY_SERVICE = contextClass.GetStatic<string>("TELEPHONY_SERVICE");
        AndroidJavaObject telephonyService = currentActivity.Call<AndroidJavaObject>("getSystemService", TELEPHONY_SERVICE);
        var imei = telephonyService.Call<string>("getDeviceId");
        result = imei;
#elif UNITY_IOS && !UNITY_EDITOR
        result = iGetIDFA();
#endif
        return result;
    }

    /// <summary>
    /// 运营商
    /// </summary>
    /// <returns></returns>
    public static string GetMobileCarrier()
    {
        string mobileCarrier = "";
#if UNITY_ANDROID && !UNITY_EDITOR
        var currentActivity = GetCurrentActivity();
        var apiInstance = GetApiInstance();
        if (currentActivity != null && apiInstance != null)
            mobileCarrier = apiInstance.Call<string>("GetMobileCarrier", currentActivity);
#elif UNITY_IOS && !UNITY_EDITOR
        mobileCarrier = iGetMobileCarrier();
#endif

        return mobileCarrier;
    }

    /// <summary>
    /// WIFI 2G 3G 4G
    /// </summary>
    /// <returns></returns>
    public static string GetNetworkType()
    {
        string networkType = "";
#if UNITY_ANDROID && !UNITY_EDITOR
        var currentActivity = GetCurrentActivity();
        var apiInstance = GetApiInstance();
        if (currentActivity != null && apiInstance != null)
            networkType = apiInstance.Call<string>("GetNetworkType", currentActivity);
#elif UNITY_IOS && !UNITY_EDITOR
        networkType = iGetNetworkType();
#endif

        return networkType;
    }

    /// <summary>
    /// 获取刘海屏宽度
    /// </summary>
    /// <returns></returns>
    public static float GetNotchScreenSize()
    {
        float result = 0.0f;
#if UNITY_ANDROID && !UNITY_EDITOR
#elif UNITY_IOS && !UNITY_EDITOR
        result = iGetNotchScreenSize();
#endif
        return result;
    }

    /// <summary>
    /// 移动机型
    /// </summary>
    /// <returns></returns>
    public static string GetMobileName()
    {
        return SystemInfo.deviceModel;
    }
}

        iOS代码:

//
//  Utility.m
//  Unity-iPhone
//
//  Created by 张平 on 2019/2/15.
//

#import <Foundation/Foundation.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>
#import <AdSupport/AdSupport.h>
#import <UIKit/UIKit.h>
#import "Reachability.h"

char* iGetMobileCarrier()
{
    //获取本机运营商名称
    CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
    CTCarrier *carrier = [info subscriberCellularProvider];
    
    //当前手机所属运营商名称
    NSString *mobile;
    
    //先判断有没有SIM卡,如果没有则不获取本机运营商
    if (!carrier.isoCountryCode) {
        NSLog(@"没有SIM卡");
        mobile = @"无运营商";
    }else{
        mobile = [carrier carrierName];
    }
    const char* output = [mobile UTF8String];

    // 是里如果直接返回_output是会报错的,因为它是是const,不能被返回。
    char* result = (char*)malloc(strlen(output)+1);
    strcpy(result, output);
    
    return result;
}

char* iGetNetworkType()
{
    NSString *netconnType = @"";
    
    Reachability *reach = [Reachability reachabilityWithHostName:@"www.apple.com"];
    
    switch ([reach currentReachabilityStatus]) {
        case NotReachable:// 没有网络
        {
            
            netconnType = @"no network";
        }
            break;
            
        case ReachableViaWiFi:// Wifi
        {
            netconnType = @"Wifi";
        }
            break;
            
        case ReachableViaWWAN:// 手机自带网络
        {
            // 获取手机网络类型
            CTTelephonyNetworkInfo *info = [[CTTelephonyNetworkInfo alloc] init];
            
            NSString *currentStatus = info.currentRadioAccessTechnology;
            
            if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyGPRS"]) {
                
                netconnType = @"GPRS";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyEdge"]) {
                
                netconnType = @"2.75G EDGE";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyWCDMA"]){
                
                netconnType = @"3G";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyHSDPA"]){
                
                netconnType = @"3.5G HSDPA";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyHSUPA"]){
                
                netconnType = @"3.5G HSUPA";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyCDMA1x"]){
                
                netconnType = @"2G";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyCDMAEVDORev0"]){
                
                netconnType = @"3G";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyCDMAEVDORevA"]){
                
                netconnType = @"3G";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyCDMAEVDORevB"]){
                
                netconnType = @"3G";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyeHRPD"]){
                
                netconnType = @"HRPD";
            }else if ([currentStatus isEqualToString:@"CTRadioAccessTechnologyLTE"]){
                
                netconnType = @"4G";
            }
        }
            break;
            
        default:
            break;
    }
    
    const char* output = [netconnType UTF8String];
    
    // 是里如果直接返回_output是会报错的,因为它是是const,不能被返回。
    char* result = (char*)malloc(strlen(output)+1);
    strcpy(result, output);
    
    return result;
}

char* iGetIDFA()
{
	NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
	
	const char* output = [idfa UTF8String];
	
	// 是里如果直接返回_output是会报错的,因为它是是const,不能被返回。
    char* result = (char*)malloc(strlen(output)+1);
    strcpy(result, output);
    
    return result;
}

float iGetNotchScreenSize()
{
	//iOS 11 以下的默认不存在刘海儿(没有谁iphone X 刷回ios 10 系统吧。哈哈)
    if (__IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_11_0) {
        return 0.0f;
    }
    
    /* iPhone8 Plus  UIEdgeInsets: {20, 0, 0, 0}
     * iPhone8       UIEdgeInsets: {20, 0, 0, 0}
     * iPhone XR     UIEdgeInsets: {44, 0, 34, 0}
     * iPhone XS     UIEdgeInsets: {44, 0, 34, 0}
     * iPhone XS Max UIEdgeInsets: {44, 0, 34, 0}
     */
    //ios 11 以上提供专门方法获取刘海儿高度
    UIEdgeInsets safeAreaInsets = UIApplication.sharedApplication.windows.firstObject.safeAreaInsets;
    
    CGFloat bottomSpace = 0;
    switch (UIApplication.sharedApplication.statusBarOrientation) {
        case UIInterfaceOrientationPortrait:{
            bottomSpace = safeAreaInsets.top;
        }break;
        case UIInterfaceOrientationLandscapeLeft:{
            bottomSpace = safeAreaInsets.left;
        }break;
        case UIInterfaceOrientationLandscapeRight:{
            bottomSpace = safeAreaInsets.right;
        } break;
        case UIInterfaceOrientationPortraitUpsideDown:{
            bottomSpace = safeAreaInsets.bottom;
        }break;
        default:
            bottomSpace = safeAreaInsets.bottom;
            break;
    }

	return (float)bottomSpace;
}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值