본문 바로가기
Programming/Unity

유니티 안드로이드 JAR 플러그인 생성방법 (Unity Android Plugin JAR)

by ▒◈§№▩ 2022. 9. 24.

Unity 게임 개발 중 안드로이드 폰에서 안드로이드만의 특정 기능이 필요할 때가 있는데 이때 안드로이드  JAR 플러그인 생성 방법을 알아보도록 하겠습니다.

안드로이드 스튜디오에서 새프로젝트 생성 후 Empty Activity 선택합니다.

새프로젝트 생성

 

프로젝트 이름, 패키지이름,프로젝트 위치 등을 지정해주고 Finish 해줍니다.

프로젝트 저장

Unity Activity를 상속을 받으려면 Unity 라이브러리를 프로젝트에 포함시켜야 합니다.

아래 공식 문서에서 위치를 확인 후 본인 pc에 맞게 찾으면 됩니다.

https://docs.unity3d.com/kr/2018.1/Manual/AndroidUnityPlayerActivity.html

 

저의 PC 에서는 Windows 기준에서 아래 2군데에 존재합니다.

Mono

C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes\classes.jar

 

IL2CPP

C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Classes\classes.jar

 

자신의 빌드 상황에 맞게 선택하면 될 거 같습니다. (참고로 2개 파일 winmerge 프로그램 비교해보면 바이너리 파일이 동일하다고 나오는데 두 개다 같은 거 아닌가 싶습니다.)

 

저는 Mono에 classes.jar 파일을 선택해서 사용하였습니다.

파일 복사 후 아래 경로의 libs 폴더에 붙여 넣기 하면 아래와 같이 창이 뜨는데 이때 ok 버튼을 눌러줍니다.

classes.jar 파일 복사 붙여넣기

 

아래와 같이 classes.jar 파일이 복사됩니다.

classes.jar 파일 복사 완료

 

아래와 같이 build.gradle(Module: app)을 열어서 맨 위에 apply plugin: 'com.android.application'에서 apply plugin: 'com.android.library'로 변경해줍니다. 이후 아래 3곳을 주석처리 해준 후 Sync Now를 눌러줍니다.

//applicationId "com.test.aaa.plugintest"

//versionCode 1

//versionName "1.0"

 

MainActivity.java 페이지로 이동 후 아래와 같이 상속 부분을 UnityPlayerActivity로 변경해주면 에러 없이 상속받을 수 있게 됩니다. 아래 예제 코드는 현재 폰의 통신상태가 연결되어있는 국가코드를 받아오는 코드를 넣었습니다. 이렇게 만든 GetCountryCode() 함수를 Unity에서 호출하여 사용할 예정입니다.

그리고 setContentView(R.Layout.activity_main);은 주석처리하였습니다.

package com.test.aaa.plugintest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {

    static String mCountryCode = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);

        TelephonyManager tm = (TelephonyManager)this.getSystemService(this.TELEPHONY_SERVICE);
        String countryCodeValue = tm.getNetworkCountryIso();
        if (countryCodeValue != null) {
            mCountryCode = countryCodeValue.toUpperCase();
            Log.d("PluginTest", "countryCodeValue.toUpperCase() : " + mCountryCode);
        }
    }

    public static String GetCountryCode() {
        Log.d("PluginTest", "GetCountryCode() : " + mCountryCode);
        return mCountryCode; //KR
    }
}

 

이제 코드가 완성되었으므로 jar 파일을 생성해 보겠습니다.

우선 아까 수정하였던 build.gradle(Module: app) 파일을 열어서 맨 아래줄에 아래와 같이 추가해 줍니다.

그리고 다시 Sync Now 해줍니다.

task deleteObjectJar(type: Delete){
    delete 'release/PluginTest.jar'
}

task exportJar(type: Copy){
    from('build/intermediates/packaged-classes/release/')
    into('release/')
    include('classes.jar')
    rename('classes.jar', 'PluginTest.jar')
}

exportJar.dependsOn(deleteObjectJar, build)

from 경로는 build/intermediates/packaged-classes/release/ 이렇게 했을 때 jar 파일이 생성되지 않았다면 

build/intermediates/bundles/release/ 이렇게 해주면 됩니다.

 

Gradle -> PluginTest -> app -> Tasks -> other -> exportJar를 더블클릭해줍니다.

jar 파일 생성

 

빌드가 완료 후 아래와 같이 BUILD SUCCESSFUL 메시지가 뜨고 D:\client\PluginTest\app\release로 이동하게 되면 PluginTest.jar 파일이 생성된 것을 확인할 수가 있습니다.

jar 파일 생성 성공

 

PluginTest.jar 파일을 유니티가 설치된 Assets\Plugins\Android에 넣어줍니다.

 

이제 유니티에서 안드로이드에서 만든 GetCountryCode() 함수를 아래와 같이 코드 생성하여 빈 오브젝트에 붙여서 클릭 시 국가코드를 안드로이드에서 가져올 수 있도록 하겠습니다.

using UnityEngine;

public class PluginTest : MonoBehaviour
{
    public static PluginTest Static;
    private AndroidJavaObject javaObj;

    private void Awake()
    {
        Static = this;
        DontDestroyOnLoad(gameObject);
    }

    void OnDestroy()
    {
        Static = null;
    }

    void Start()
    {
        javaObj = new AndroidJavaObject("com.test.aaa.plugintest.MainActivity");
        if (javaObj != null)
        {
            Debug.Log("====================javaObj != null");
        }
        else
        {
            Debug.Log("====================javaObj == null");
        }
    }

    public void ONCLICK_GETCOUTNRY()
    {
        Debug.Log("<PluginTest> ONCLICK_GETCOUTNRY()");

        var Code = javaObj.CallStatic<string>("GetCountryCode");
        Debug.Log("ONCLICK_GETCOUTNRY() Result = " + Code);
    }
}

 

기존에 Assets\Plugins\Android\AndroidManifest.xml 파일을 열어서 com.unity3d.player.UnityPlayerActivity를 안드로이드 스튜디오에서 메인 액티비티인 com.test.aaa.plugintest.MainActivity로 변경해줍니다.

 

변경 전

<activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name">

 

변경 후

<activity android:name="com.test.aaa.plugintest.MainActivity" android:label="@string/app_name">

 

수정 결과는 아래와 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.norion.p007" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:name="androidx.multidex.MultiDexApplication" android:theme="@style/UnityThemeSelector" android:icon="@mipmap/app_icon" android:label="@string/app_name" android:usesCleartextTraffic="true">
    <activity android:name="com.test.aaa.plugintest.MainActivity" android:label="@string/app_name">  <!-- ================== 기존 코드에서 여기에 name 부분만 바꿔줬음 -->
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>	
    <activity android:name="com.facebook.unity.FBUnityLoginActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
    <activity android:name="com.facebook.unity.FBUnityDialogsActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
    <activity android:name="com.facebook.unity.FBUnityAppLinkActivity" android:exported="true" />
    <activity android:name="com.facebook.unity.FBUnityDeepLinkingActivity" android:exported="true" />
    <activity android:name="com.facebook.unity.FBUnityGameRequestActivity" />
    <activity android:name="com.facebook.unity.FBUnityCreateGameGroupActivity" />
    <activity android:name="com.facebook.unity.FBUnityJoinGameGroupActivity" />
    <activity android:name="com.facebook.unity.AppInviteDialogActivity" />
    <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="fb772073929601405" />
    <provider android:name="com.facebook.FacebookContentProvider" android:authorities="com.facebook.app.FacebookContentProvider772073929601405" android:exported="true" />
    <activity android:name="com.facebook.unity.FBUnityGamingServicesFriendFinderActivity" android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen" android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
    <meta-data android:name="com.facebook.sdk.AutoLogAppEventsEnabled" android:value="true" />
    <meta-data android:name="com.facebook.sdk.AdvertiserIDCollectionEnabled" android:value="true" />
  </application>
</manifest>

 

빌드 후 테스트 결과 버튼 클릭 시 국가코드를 제대로 받아 오는 걸 확인할 수 있다.

이상으로 유니티에서 안드로이드 JAR Plugin을 생성하여 안드로이드에서만 사용할 수 있는 코드를 작성해 보았습니다.

 

[참고]

확인 결과 안드로이드 프로젝트 생성 시 패키지 네임과 유니티 설정창에 패키지 네임이 굳이 같을 필요는 없는 거 같습니다.

 

[확인해볼 사항]

mono에 있는 classes.jar로 사용하고 유니티 빌드에서는 IL2CPP로 빌드했을 때 문제없는지 확인해보자.

그리고 반대 상황도 확인해 보자.

이유는 mono가 유니티 빌듯이 속도가 빨라서 테스트 상황에서는 mono로 빌드를 자주 하는데 라이브 버전에서는 IL2CPP로 빌드를 해야 한다. 이럴 경우 또 안드로이드 라이브러리 바꿔서. jar 파일을 다시 뽑아야 하는 번거로움이 있기 때문에 classes.jar 파일 맞지 않아도 상관없는지 확인해 볼 필요가 있다. 그런데 두 개 파일을 winmearg 프로그램으로 비교해보면 바이너리 파일이 같아서 문제없을 거 같긴 하다.

 

댓글