DEV Community

armariya
armariya

Posted on • Originally published at Medium on

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

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

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

  • Android studio
  • Unity3d 2018.2.0f2

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

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

สร้าง Moudle ใหม่เป็น Android Library

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

เอา Line SDK for Android ใส่ในโปรเจค

จากนั้นก็เขียนโค้ดสำหรับ 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.cs

public 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 นะครับ ถ้าเกิดเราไม่ใส่อันนี้เข้าไปเนี่ยมันจะหาไม่เจอครับบ

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

คุยกันได้ ที่นี่ ปล. page นี้ผมเคยเปิดทิ้ง ๆ ไว้ เอาไว้เป็นที่คุยละกันครับ 555

Top comments (2)

Collapse
 
chanyut profile image
Chanyut Leecharoen

สอบถามหน่อยพอดีผม integrate plugin ที่เขียนด้วย kotlin เข้า แล้วเจอปัญหา kotlin stdlib conflict กัน ระหว่าง 1.3.11 กับ 1.3.40 ผมลองดูแล้ว unity มันใส่ 1.3.11 มาให้ใน build.gradle แต่ตอน jar resolve มันเอา 1.3.40 น่ะครับ พอมีทางกำหนด version kotlin ให้ใช้แค่ version เดียวได้มั้ยครับ

Collapse
 
armariya profile image
armariya

พอดีเพิ่งเห็นน่ะครับ คือ custom gradle มาแล้ว แล้วก็ใส่ 1.3.40 ไปแล้วในอันสุดท้ายมันมี 1.3.11 ยัดมาด้วยแบบนี้เหรอครับ ถ้าเป็นไปได้พอจะมี โปรเจคที่เป็นที่เล็กที่สุดไหมครับ เผื่อจะได้ลองช่วยดูได้