起因

最近项目需要统计手机的运营商和 WiFi 、4G 等情况,这个时候必须调用机器的 Native 代码

使用

这里不对如何获取运营商做详细的介绍,主要介绍如何完成 Unity 和 Android Native 之间的交互

运营商代码参考

路径参考

Assets
├── Plugins
│   └── Android
│       ├── AndroidManifest.xml
│       └── MainActivity.java
└── Scripts
    └── MobileHelper.cs

MainActivity.java

// 你的包名
package com.xxx.xxx;

import com.unity3d.player.*;

public class MainActivity extends UnityPlayerActivity {
    public int Test(){
        return 123;
    }
    
    public static int TestStatic() {
        return 456;
    }
}

AndroidManifest.xml

这里需要修改为自己的包名

<?xml version="1.0" encoding="utf-8"?>
<manifest
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.xxx.xxx"
        android:installLocation="preferExternal"
        android:theme="@android:style/Theme.NoTitleBar"
        android:versionCode="1"
        android:versionName="1.0">

    <application android:allowBackup="false" tools:replace="android:allowBackup" android:usesCleartextTraffic="true">
        <uses-library android:name="org.apache.http.legacy" android:required="false"/>
        <activity android:name="com.xxx.xxx.MainActivity"
                  android:launchMode="singleTask"
                  android:label="@string/app_name"
                  android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="false"/>
        </activity>
        
    </application>

</manifest>

MobileHelper.cs

使用时,在外部直接调用里面的静态方法即可

public class MobileHelper {
    public static AndroidJavaObject CurrentActivity {
        get
        {
            if(_currentActivity == null){
                _currentActivity =
                    new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>(
                        "currentActivity"
                    );
            }

            return _currentActivity;
        }
    }
    public static int Test() {
        int result = 0;
#if UNITY_ANDROID && !UNITY_EDITOR
        if(CurrentActivity != null) {
            result = CurrentActivity.Call<int>("Test");
        }
#endif
        return result;
    }
    
    public static int TestStatic() {
        int result = 0;
#if UNITY_ANDROID && !UNITY_EDITOR
        if(CurrentActivity != null) {
            result = CurrentActivity.CallStatic<int>("Test");
        }
#endif
        return result;
    }
}

排坑

Unity 调用 Native 就简单的几行代码即可, 但是在我的项目中就一直报找不到该方法的错误

后面就是无尽的错误排查,直到 PlayerSetting -> Publishing Setting 中的 Minify

我项目出错的时候,选的是第三个 Gradle,这个时候会裁剪你的代码,导致该函数无法正确被调用

但是!我们接入的是 MSDK,这套大礼包自己维护了一套 Gradle 构建,如果选择 None 就会导致 MSDK 无法正常运行

解决方案如下,需要导入 Keep 关键字需要的库,然后在被裁剪的函数上增加 @Keep 关键字即可完美运行

import android.support.annotation.Keep;
@Keep
public int Test() {
    xxxxx
}

不了解安卓构建,被这个问题坑惨了 T^T


What doesn’t kill you makes you stronger.