자마린(Xamarin)

JNI를 이용하여 Xamarin.Android에서 안드로이드 SDK에서 만든 .jar의 클래스/메소드를 호출하는 실습(Java…

FSP 0 191 01.29 23:02

JNI를 이용하여 Xamarin.Android에서 안드로이드 SDK에서 만든 .jar의 클래스/메소드를 호출하는 실습(Java Native Invoke By JNIEnv)

Xamarin.Android 이용하면 Java 대신 C#에서 Android 앱을 작성할  있다.

Mono.Android.dll  Mono.Android.GoogleMaps.dll 비롯하여 Java 라이브러리에 대한 바인딩을 제공하는 많은 것들이 Xamarin.Android 에서 제공되지만,모든 Java 라이브러리에 대한 C# 바인딩이 제공되지 않으며 모든 Java 유형  멤버를 바인드하지  할수도 있다.

n Java 코드를 호출하기 위해 Managed Callable Wrapper (MCW)를 만드는 것이 필수는 아니다. 대부분 인라인 JNI는 언 바운드 Java 멤버에 대해 호출이 가능한데, 전체 JAR 바인딩을 생성하는 것보다 JNI를 사용하여 Java 클래스에서 하나의 메소드를 호출하는 것이 더 간단할 수 있다.

 바운드 Java 유형  멤버를 사용하려면 JNI (Java Native Interface) 사용할  있는데 JNI 사용하여 Xamarin.Android 애플리케이션에서 Java 클래스 멤버와 상호 작용하는 방법을 살펴보자.

n Xamarin.Android의 JNI API는 개념적으로 .NET의 System.Reflection API와 매우 유사하며 타입 및 멤버를 이름으로 검색하고 필드 값을 읽고 쓰며 메소드를 호출하는 등의 작업을 수행 할 수 있다.

n Android.Runtime.JNIEnv 네임스페이스를 통해 노출 된 JNI는 모든 버전의 Xamarin.Android에서 사용할 수 있으며 Java 타입 및 인터페이스를 바인딩하려면 Xamarin.Android 4.0 이상을 사용해야 한다.

n 자바 jar 파일인 경우 임의의 jar 파일의 바인딩을 지원하지 않고 Android SDK에서 만들어진 .jar만 바인딩 가능하다.

n Android.Runtime.JNIEnv를 이용하여 Java 객체의 인스턴스를 만들고 C#에서 Java 객체의 메소드를 호출할 수 있으며 Java 소스 코드(AndroidJavaSource로 포함) 및 .jar 파일(AndroidJavaLibrary로 포함)을 결과 Android 애플리케이션에 포함 할 수도 있다.

1. 안드로이드 스튜디오(Android Studio)에서 jar 파일 생성실습

안드로이드 스튜디오에서 새로운 프로젝트를 생성하고 location, application name, company domain 기술하고 다음 페이지 Target Android Device에서“Phone and Tablet” 선택

n Add an Activity to Mobile 화면에서 “Add No Activity”를 선택 후 “Finish” 클릭

n Xamarin.Android에서 JNI를 통해 호출될 두수의 합을 구하는 Adder 클래스를 작성하자.

Build.gradle(Module : sayhello)

apply plugin: 'com.android.library'

//task to delete the old jar

task deleteJar(type:Delete){

delete 'libs/adder.jar'

}

//task to export contents as jar

task exportJar(type:Copy){

//from('build/intermediates/bundles/release/') //안드로이드 3.1 하위버전

from('build/intermediates/intermediate-jars/release/') //안드로이드 3.1 이상버전

into('libs/')

include('classes.jar')

rename('classes.jar','adder.jar')

}

exportJar.dependsOn(deleteJar, build)

android {

compileSdkVersion 28

defaultConfig {

//응용프로그램이 아니라 라이브러리 이므로 생략

//applicationId "com.example.sayhello"

minSdkVersion 15

targetSdkVersion 28

versionCode 1

versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {

release {

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

}

dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'com.android.support:appcompat-v7:28.0.0-rc02'

testImplementation 'junit:junit:4.12'

androidTestImplementation 'com.android.support.test:runner:1.0.2'

androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

}

n 안드로이드 스튜디오 우측의 Gradle을 클릭 후 :sayhello -> Tasks -> other -> exportJar 태스크를 더블 클릭하여 실행(exportJar Task가 보이지 않으면 Gradle Project 상단 좌측의 refresh 버튼을 클릭하자.)

n 이제 sayhello\libs 폴더에 adder.jar 파일이 생성되었다.

2. 비주얼 스튜디오에서 Xamarin.Android 프로젝트를 생성하여 adder.jar 파일을 JNIEnv를 이용하여 Adder 클래스의 add 메소드를 호출하자.

JniTest라는 이름으로 Xamarin.Android 프로젝트를 생성하자.

n 프로젝트 생성 후 안드로이드 스튜디오에서 작성한 adder.jar 파일을 추가하자. adder.jar 파일을 Xamarin.Android 프로젝트에 추가할 때는 프로젝트 >> 추가 >> 기존항목에서 jar 파일을 선택 후 “Add to Link(링크로 연결)”을 선택하는 것이 jar 파일이 바뀔 때 마다 다시 복사하는 번거러움이 없을 것이다.

n 주의 : adder.jar 파일을 선택 후 속성창의 빌드작업(Build Action)을 “AndroidJavaLibrary”로 설정해야 한다.

[activity_main.axml]

[MainActivity.cs]

using Android.App;

using Android.OS;

using Android.Runtime;

using Android.Support.V7.App;

using Android.Widget;

using System;

namespace JniTest

{

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]

public class MainActivity : AppCompatActivity

{

protected override void OnCreate(Bundle savedInstanceState)

{

base.OnCreate(savedInstanceState);

// Set our view from the "main" layout resource

SetContentView(Resource.Layout.activity_main);

EditText op1 = FindViewById<EditText>(Resource.Id.editText1);

EditText op2 = FindViewById<EditText>(Resource.Id.editText2);

Button button1 = FindViewById<Button>(Resource.Id.button1);

TextView result = FindViewById<TextView>(Resource.Id.result);

button1.Click += (sender, args) =>

result.Text = Adder(int.Parse(op1.Text), int.Parse(op2.Text));

}

string Adder(int op1, int op2)

{

// 자바클래스의 핸들(포인터)을 취득

IntPtr jClass = JNIEnv.FindClass("com/example/sayhello/Adder");

// 기본 생성자 포인터 취득

IntPtr defaultConstructor = JNIEnv.GetMethodID(jClass,

"<init>",

"()V");

// 새인스턴스(객체) 생성 후 포인터 취득

IntPtr instance = JNIEnv.NewObject(jClass, defaultConstructor);

// sayHello 메소드 포인터 취득

IntPtr method = JNIEnv.GetMethodID(jClass,"add", "(II)I");

// 메소드 파라미터 정의 및 호출 후 결과값을 받음

JValue[] paramOp = new JValue[] {

new JValue(op1),

new JValue(op2),

};

int result = JNIEnv.CallIntMethod(instance, method, paramOp);

return result.ToString();

}

}

}

실행결과

(자마린.안드로이드)JNI를 이용하여 Xamarin.Android에서 안드로이드 SDK에서 만든 .jar의 클래스/메소드를 호출하는 실습(JNIEnv를이용한자바네이티브호출)

#자마린, #Xamarin, #JNI, #자마린JNI, #자마린교육, #자마린강좌, #자마린강의 

, , , , , ,

Comments