เขียน Plugin Android สำหรับ Unity3d ด้วย Kotlin เพื่อรับผลจาก onActivityResult โดยไม่ต้อง override activity หลัก

qapquiz
qapquiz
Jul 18, 2018 · 3 min read

สวัสดีครับบ วันนี้มาเป็นเรื่องเกี่ยวกับการเขียน Plugin Android บน Unity3d ที่ตัดสินใจมาเขียนนี่เพราะว่า รู้สึกว่าตอนผมทำเนี่ยมันหาอ่านยากมากเลย เลยมาเขียนเก็บไว้ตรงนี้ เพื่อคนต่อ ๆ ไปนะครับบ เดี๋ยวจะทำให้ดูคร่าว ๆ นะครับไม่งั้นมันจะยาวโคตร

Requirement สำหรับวันนี้

  • Android studio
  • Unity3d 2018.2.0f2

ครับผม สำหรับคนที่มีครบทุกอย่างแล้ว ก็เริ่มกันเลย! โดยสำหรับวันนี้จะมาทำ Line Login กันดูนะครับ

เปิด Android Studio ขึ้นมาทำงานกันโลด ทำการสร้างโปรเจคบน Andriod แล้ว New Module ใหม่ขึ้นมาเป็น Android Library สักหนึ่งที

จากสร้าง Activity ใหม่ชื่อว่า LineSDKActivity ขึ้นมาครับ จากนั้นเราจะมาเริ่มเขียนตัว Plugin กันนะครับ ก่อนอื่น เราต้องไป Download ตัว LineSDK สำหรับ Android จากหน้าเว็บกันก่อนเลยครับ​ (จัดการสร้าง Project อะไรให้เสร็จสรรพเลยนะครับ ลองอ่านจากหน้าเว็บมันดูนั่นแหละ) สามารถหาได้จากที่นี่ หลังจากเสร็จแล้วก็เอาตัว .aar ลากลง lib โลดเลยครับ

จากนั้นก็เขียนโค้ดสำหรับ Login เลยครับผม สามารถแทบจะลอกจากหน้าเว็บของ Developer Line ได้เลยครับ

class LineSDKActivity : AppCompatActivity() {

companion object {
lateinit var lineLoginCallback: LineLoginCallback

fun startLineSDKActivity(activity: Activity, lineLoginCallback: LineLoginCallback) {
LineSDKActivity.lineLoginCallback = lineLoginCallback;
val intent = Intent(activity.applicationContext, LineSDKActivity::class.java)
activity.startActivity(intent);
}
}


data class PlayerProfile(
val displayName: String,
val statusMessage: String?,
val userId: String,
val pictureUri: Uri?
)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

login()
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode != Constants.REQUEST_CODE) {
Log.e("ERROR", "Unsupported Request");
lineLoginCallback.onLoginFailed("Unsupported Request")
finish()
}

if (data == null) {
lineLoginCallback.onLoginFailed("Can't connect with Line")
finish()
}

val result: LineLoginResult = LineLoginApi.getLoginResultFromIntent(data)

when (result.responseCode) {
LineApiResponseCode.SUCCESS -> {
lineLoginCallback.onLoginSuccess(
result.lineProfile!!.displayName
)
}
else -> {
lineLoginCallback.onLoginFailed("Login Unsuccessful")
}
}

finish()

}

fun login() {
startActivityForResult(getLineLoginIntent(), Constants.REQUEST_CODE)
}

private fun getLineLoginIntent() : Intent {
return LineLoginApi.getLoginIntent(this.applicationContext, Constants.CHANNEL_ID)
}
}

หลังจากได้ประมาณนี้ปุ๊บ จะเห็นว่าผมมีใช้ตัว LineLoginCallback เพื่อให้สามารถเอาไปเชื่อมกับตัว C# ใน Unity3d ได้ ก็ทำการสร้างไฟล์ใหม่แล้วประกาศ interface โลด

interface LineLoginCallback {
fun onLoginSuccess(displayName: String)
fun onLoginFailed(errorMessage: String)
}

หลังจากเสร็จ อย่าลืมว่าต้องใส่ appcompat กับ customtabs ให้กับ build.gradle ของตัว ​module นี้ด้วยนะครับ แบบนี้

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
implementation 'androidx.browser:browser:1.0.0-beta01'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation(name: 'line-sdk-4.0.8', ext: 'aar')
}

แล้วก็ทำการ build โลดเลยครับ ถ้า build สำเร็จเราก็จะได้เป็นไฟล์ .aar มาอยู่ใน output ของ module นะครับ

คราวนี้เรามาดูที่ตัว Unity ของเรากันบ้าง ที่นี่เราต้องทำการสร้างโฟลเดอร์ Plugins/Android ขึ้นมาครับ เพื่อเป็นที่เก็บตัว Plugin ของเราตามกฏของ Unity นะครับ

จากนั้นเอา .aar ของเรายัดเข้าไปเลยครับ รวมถึงไฟล์ line-sdk-4.0.8.aar ที่โหลดมาจากเว็บของ Line ด้วยนะครับ จากนั้น เราจะทำการเปิด gradle ไฟล์ขึ้นมา เพื่อจัดการตัว Dependencies ในโปรเจคนะครับ ไปที่ build setting ของ Android ในส่วนของ Publishing Settings ทำการติ้กถูกตรง Custom Gradle Template โลดเลยครับ ตามรูปข้างล่าง

เราจะได้ไฟล์ mainTemplate.gradle ขึ้นมานะครับแล้วทำการ แก้ไขโลดเลยครับ

implementation(name:'line-sdk-4.0.8', ext:'aar')
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.51'
implementation 'androidx.appcompat:appcompat:1.0.0-alpha1'
implementation 'androidx.browser:browser:1.0.0-alpha1'

ทำการ add สี่ตัวนี้เข้าไปที่ส่วนของ Dependencies ได้เลยครับ จากนั้น ผมจะเขียนคร่าว ๆ ของส่วนการใช้ให้ดูนะครับ จะประมาณนี้ก็คือ ก่อนอื่นสร้างไฟล์ขึ้นมาก่อน สำหรับผมใช้ชื่อ LineSDK.cs นะครับ

// LineSDK.cspublic class LineSDK {
public class LineLoginCallback : AndroidJavaProxy {
public LineLoginCallback : base("xxx.xx.xxx.LineSDKActivity") {}

public void onLoginSuccess(string displayName) {
Debug.Log("Line login success");
}
public void onLoginFailed(string errorMessage) {
Debug.Log("Line login failed");
}
}
...
}

อันนี้เป็นส่วนหลักเลยนะครับ อันนี้สังเกตนะครับ LineLoginCallback สืบทอดมาจาก AndroidJavaProxy โดยใน constructor เนี่ยเอามาจากชื่อ Class ของใน Java ที่เราประกาศ interface ไว้นะครับ

ส่วนตอน function login เนี่ยก็จะประมาณนี้ครับ

สุดท้ายยยนะครับ อย่าลืมใส่ AndroidManifest.xml ใน Unity3d ด้วยนะครับ​ โดยมันจะมี Template อยู่นะครับ แต่เดี๋ยวผมเอาแต่ส่วนสำคัญที่จำเป็นต้องเพิ่มมาให้ดูละกันครับ

...<activity
android:name="app.zosimos.linesdk.LineSDKActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
/>
...

อันนี้คือการที่เราเพิ่ม Activity ที่เราเขียนใน Java เพิ่มเข้าไปใน Unity นะครับ ถ้าเกิดเราไม่ใส่อันนี้เข้าไปเนี่ยมันจะหาไม่เจอครับบ

ก็จะประมาณนี้แหละครับ ต้องขอโทษที พอดีบล๊อกนี้รีบเขียนไปหน่อย แต่ยังไงก็ถ้ามีอะไรก็ทักมาถามกันได้ครับ อาจจะพอให้เป็นแนวทางได้ ขอบคุณครับ

qapquiz

Written by

qapquiz

Arm | I'm a Game Developer | My dream job is Imagineer!