해당 내용은 Android 기기에서 Unity를 실행하여 APK를 Android Plugin을 이용해 APK를 실행하여 설치를 진행하도록 하는 내용이다. 진행 이전에 알아둬야 될 점은 'APK를 실행하여 설치' 해야 되는 부분이다. Android 기기에서 APK 파일을 실행했을 때 나오는 설치 화면이 나오며 Unity 상에서 자연스럽게 설치하는 내용이 아니다.

 

APK를 실행하여 설치하는 부분은 Android 기능이기 때문에 굳이 Plugin을 만들어서 Unity에서 요청할 이유는 없다. 그저 Android 개발에 대하여 모르기 때문에 Plugin 구현은 검색을 통해 해결하고 Unity로 진행을 했다.

 

 

 Android Studio에서 Plugin 만들기

 

1. 새 프로젝트 생성

UnityPlugin 이라는 이름의 빈 프로젝트를 생성한 뒤 File -> New -> New Module,  Android Libray를 생성한다. 이름은 plugin 으로 작성한다.

 

2. Unity의 classes.jar 파일을 복사해서 프로젝트의 plugin/libs 폴더에 복사한다.

유니티 설치 경로/Editor/Data/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Release/Classes

 

이때 jar 파일을 app/libs에 복사하지 않도록 주의한다. 새로 추가한 plugin의 libs에 복사해야 한다.

 

3. build.gradle (Module:UnityPlugin.plugin) 수정

dependencies의 compileOnly fileTree()를 추가하고, 우측 상단에 나오는 Sync Now를 클릭한다.

이는 libs에 추가한 Unity의 jar 파일을 사용하기 위함이다.

 

4. 프로젝트를 AndroidX로 마이그레이션

상단의 Refactor -> Migrate to AndoridX 를 눌러 진행한다.

진행을 하지 않으면 androidx 관련 패키지를 사용하는데 에러가 발생한다.

 

5. 코드 작성

plugin 모듈에 UnityPlugin 이라는 이름의 java class를 생성한 뒤 아래의 코드로 덮어씌운다.

 

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.core.content.FileProvider;

import java.io.File;

public class UnityPlugin extends Activity {
    static String errMessage;

    public static String InstallApp(Context context, String ApkPath){
        try {
            errMessage = "test";
            File toInstall = new File(ApkPath);
            Uri apkUri = FileProvider.getUriForFile(context,
                    context.getPackageName() +
                            ".fileprovider", toInstall);
            Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
            intent.setData(apkUri);
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
        catch (Exception e){
            errMessage = e.getMessage();
        }
        return errMessage;
    }
}

 

추가로 ContextClass 라는 java class도 만든다.

import android.app.Application;
import android.content.Context;

public class ContextClass extends Application {
    private  static ContextClass instance;

    public ContextClass(){
        instance = this;
    }

    public static ContextClass instance(){
        return instance;
    }

    public static Context context() {
        return instance.getApplicationContext();
    }
}

 

6. 빌드

우측의 Gradle 탭을 클릭하고 plugin/Tasks/build/assemble를 더블클릭한다.

app의 assemble을 빌드하지 않도록 주의한다.

 

빌드가 완료되면 plugin/build/outputs/aar 폴더에 파일이 생성된 것을 확인할 수 있다.

 

7. Unity에 추가하기

생성된 aar 파일을 Unity의 Assets/Plugins/Android 경로에 복사한다.

 

 

Unity에서 Plugin 사용하기

 

1. AndroidManifest.xml 만들기

아래의 내용으로 Plugin/Android 경로에 생성해준다.

이때 com.your.package 이라고 작성된 부분이 2곳 있는데 Unity 프로젝트에서 사용하는 패키지로 수정한다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.your.package" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal" android:versionName="1.0" android:versionCode="1">
  <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" />
  <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="true">
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_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>

    <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="com.your.package.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
      <meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/provider_paths"/>
    </provider>

  </application>
  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-sdk android:minSdkVersion="26" android:targetSdkVersion="26" />
</manifest>

 

2. provider_paths.xml 만들기

Unity 프로젝트의 Assets/Plugins/Android/res/xml 경로에 provider_paths.xml 파일을 만들고 아래의 코드를 작성한다.

이때 com.your.package 이라고 작성된 부분이 1곳 있는데 Unity 프로젝트에서 사용하는 패키지로 수정한다.

 

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
  <!--<external-path name="external_files" path="."/>-->
  <external-path path="Android/data/com.your.package" name="files_root" />
  <external-path path="." name="external_storage_root" />
</paths>

 

3. Unity에 AndroidX aar 파일 추가하기

mvnrepository에서 androidx aar 파일을 다운로드 받아 Unity의 Assets/Plugins/Android 경로에 추가한다.

https://maven.google.com/androidx/core/core/1.0.1/core-1.0.1.aar

 

4. C# 스크립트 추가하기

작성한 Android Plugin을 이용해 APK를 실행하는 코드이다.

APK 파일 다운로드 코드는 생략했으며 파일이 존재한다는 것을 전제로 작성되어 있다.

 

    public void Install(string path)
    {
		try
		{
			AndroidJavaClass unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
			AndroidJavaObject unityActivity = unityClass.GetStatic<AndroidJavaObject>("currentActivity");
			AndroidJavaObject unityContext = unityActivity.Call<AndroidJavaObject>("getApplicationContext");

			AndroidJavaClass plugin = new AndroidJavaClass("com.example.plugin.UnityPlugin");
			string result = plugin.CallStatic<string>("InstallApp", unityContext, path);
		}
		catch (Exception e)
		{
			Debug.Log(e.Message);
		}
	}

 

 

5. 빌드 및 실행

정상적으로 빌드가 되고 실행이 되면 Unity 화면에서 Android 기기에서 APK 파일을 실행했을 때의 화면으로 넘어가지며 설치를 진행할 수 있다.

 

만약 빌드 및 실행 중 에러가 발생하면 아래의 내용을 진행한다.

 

 

빌드 및 실행 실패 시 추가 작업

만약 빌드 실패, 실행 시 크래시, APK 다운로드 후 실행 시 Android 혹은 Unity에서 에러 발생 시 아래의 내용들을 진행하도록 한다.

 

1. Unity에 Google unity-jar-resolver 적용하기

아래의 링크에서 최신 버전 혹은 상황에 따라 적절한 버전을 설치한다.

Assets 파일 외에 텍스트로 unitypackage 링크가 있으니 그걸 프로젝트에 추가한다.

 

https://github.com/googlesamples/unity-jar-resolver/tags

 

GitHub - googlesamples/unity-jar-resolver: Unity plugin which resolves Android & iOS dependencies and performs version managemen

Unity plugin which resolves Android & iOS dependencies and performs version management - GitHub - googlesamples/unity-jar-resolver: Unity plugin which resolves Android & iOS dependencies an...

github.com

 

정상적으로 추가가 되면 Unity Editor 상단의 Assets/External Dependency Manager/Android Resolver/Settings 를 실행한다.

 

여러가지 옵션이 나오는데 Use Jetifier. 라는 옵션을 활성화한 뒤 하단의 OK 버튼을 누른다.

 

이후 Assets/External Dependency Manager/Android Resolver/Force Resolve 를 실행한다.

 

정상적으로 진행되어 성공 내용이 나오면 빌드를 진행해본다.

 

2. Android 및 Unity의 SdkVersion 설정

Android 프로젝트의 build.gradle (Module:UnityPlugin.plugin)의 내용 중 minSdkVersion와 targetSdkVersion을 변경하고 내용을 수정하였으니 다시 aar 파일을 빌드하여 Unity에 적용한다.

 

Unity 프로젝트의 AndroidManifest 파일의 minSdkVersion과 targetSdkVersion도 변경한다.

 

이후 빌드를 진행한다.

 

 

 

참조

https://mrw0119.tistory.com/147

 

[Unity] 안드로이드 플러그인 (Android Plugin JAR, AAR)

유니티에서 사용하는 안드로이드 플러그인 파일은 두가지로 구분된다. JAR과 AAR이다. JAR은 class만 포함된 파일이고, AAR은 class + manifest + resource가 전부 포함된 파일이다. class만 사용할 경우 JAR 파

mrw0119.tistory.com

https://stackoverflow.com/questions/45080718

 

Error: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser

I am getting this error.I am new to android studio and i need to create this plugin for unity to install an apk at runtime Error - Attempt to invoke virtual method 'android.content.Context Android.

stackoverflow.com

 

Posted by Heon_Dev
,