สร้างสะพาน! การรวมกันอย่างราบรื่นระหว่าง Android และ Webapps
สร้างสะพานที่แข็งแกร่งระหว่าง Android และ Webapp ของคุณด้วยห้องสมุด SimpleEdroidbridge ไลบรารีนี้ช่วยให้คุณสามารถแสดงเว็บแอปพลิเคชันใน WebView Android และสร้าง JSInterface เพื่อเปิดใช้งานการสื่อสารที่ราบรื่นระหว่างสองแพลตฟอร์ม แบ่งปันวัตถุที่ซับซ้อนสัญญาและฟังก์ชั่นการโทรกลับทั้งหมดในขณะที่เว็บแอปพลิเคชันของคุณยังคงตอบสนองและมีประสิทธิภาพ
✓แบ่งปันวัตถุ - Android ⇄เว็บ
✓แบ่งปันสัญญา - Android ⇄เว็บ
✓ฟังก์ชั่นการโทรกลับ - Android ←เว็บ
✓ฟังก์ชั่นการโทรไม่ปิดกั้น - Android ⇄เว็บ
✓พิมพ์ความปลอดภัยด้วย TypeScript - Android + Web
สะพาน JavaScript ในตัวใน Android SDK รองรับประเภทดั้งเดิมเท่านั้น ด้วย SimpleEdroidBridge คุณสามารถแบ่งปันวัตถุที่ซับซ้อนระหว่าง Android และ Web ได้อย่างง่ายดาย เพียงกำหนดประเภทเป็นอาร์กิวเมนต์หรือค่าส่งคืนในฟังก์ชั่นดั้งเดิมของ Android และไลบรารีจะแปลงวัตถุ JavaScript เป็นวัตถุ Kotlin โดยอัตโนมัติและในทางกลับกัน
// Kotlin
class AndroidNativeInterface ( val contactService : ContactService ): DefaultJSInterface( " Android " ) {
@NativeCall( CallType . FULL_SYNC )
fun searchContact ( contactFilter : ContactFilter ): List < Contact > {
return contactService.search(contactFilter)
}
}
data class ContactFilter ( val surname : String? = null , val firstname : String? = null )
data class Contact ( val surname : String? = null , val fistname : String? = null ,
val mail : String? = null , val phonenumber : String? = null ) // Javascript
console . log ( Bridge . interfaces . Android . searchContact ( { surname : "Pitt" } ) )สะพาน JavaScript ใน Android SDK ดำเนินการฟังก์ชั่นในลักษณะการปิดกั้นทำให้เว็บแอปพลิเคชันค้างจนกว่าฟังก์ชั่นดั้งเดิมจะกลับมา อย่างไรก็ตามด้วยไลบรารีนี้คุณสามารถกำหนดประเภทการส่งคืนสัญญาซึ่งอนุญาตให้ดำเนินการไม่ปิดกั้น ด้วยการใช้ฟังก์ชั่น 'doinbackground' รหัส Android จะถูกดำเนินการในเธรดพื้นหลังเพื่อป้องกันไม่ให้เว็บแอปพลิเคชันถูกบล็อก
// Kotlin
class AndroidNativeInterface ( val contactService : ContactService ): DefaultJSInterface( " Android " ) {
@NativeCall( CallType . FULL_PROMISE )
fun searchContact ( contactFilter : ContactFilter ) = doInBackground< List < Contact >> { promise ->
try {
promise.resolve(contactService.search(contactFilter))
} catch (e : Exception ) {
promise.reject(e)
}
}
}
data class ContactFilter ( val surname : String? = null , val firstname : String? = null )
data class Contact ( val surname : String? = null , val fistname : String? = null ,
val mail : String? = null , val phonenumber : String? = null ) // Javascript
Bridge . interfaces . Android . searchContact ( { surname : "Pitt" } ) . then ( ( list ) => {
console . log ( list ) ;
} ) ;หากคุณคุ้นเคยกับ JavaScript คุณอาจไม่มีคนแปลกหน้าในการโทรกลับ SimpleEdroidBridge ใช้แนวคิดนี้อีกขั้นหนึ่งช่วยให้คุณสามารถฉีดฟังก์ชั่นการเรียกกลับ JavaScript เหล่านี้ลงในชั้น Android โดยตรงดังนั้นจึงสร้างการโต้ตอบที่ราบรื่นระหว่างเว็บแอปพลิเคชันและ Android ของคุณ
// Kotlin
class AndroidNativeInterface ( val button : Button ): DefaultJSInterface( " Android " ) {
@NativeCall( CallType . FULL_SYNC )
fun registerOnClickAction ( jsFunction : JSFunction ) {
button.setOnClickListener { jsFunction() }
}
} // Javascript
Bridge . interfaces . Android . registerOnClickAction ( ( ) => {
console . log ( "Button Clicked!" )
} ) หากต้องการส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชัน JavaScript ให้ใช้ประเภท JSFunctionWithArg ซึ่งได้รับการออกแบบมาโดยเฉพาะเพื่อยอมรับอาร์กิวเมนต์
// Kotlin
class AndroidNativeInterface ( val button : Button ): DefaultJSInterface( " Android " ) {
var i = 0
@NativeCall( CallType . FULL_SYNC )
fun registerOnClickAction ( jsFunction : JSFunctionWithArg < Int >) {
button.setOnClickListener { jsFunction( ++ i) }
}
} // Javascript
Bridge . interfaces . Android . registerOnClickAction ( ( i ) => {
console . log ( "Button Clicked! " + i )
} )หากต้องการส่งผ่านหลายอาร์กิวเมนต์ไปยังฟังก์ชั่นให้พิจารณาการสร้างคลาสข้อมูล
สำหรับฟังก์ชั่นที่จำเป็นต้องส่งคืนผลลัพธ์ไปยังเลเยอร์ Android คุณสามารถใช้ JSFunctionWithPromise สำหรับฟังก์ชั่นที่ไม่มีอาร์กิวเมนต์หรือ JSFunctionWithPromiseAndArg สำหรับฟังก์ชั่นที่ยอมรับอาร์กิวเมนต์
// Kotlin
class AndroidNativeInterface ( val button : Button ): DefaultJSInterface( " Android " ) {
@NativeCall( CallType . FULL_SYNC )
fun registerOnClickAction ( jsFunction : JSFunctionWithPromiseAndArg < Add , Int >) {
button.setOnClickListener {
val add = Add (( Math .random() * 10 ).toInt(), ( Math .random() * 10 ).toInt())
jsFunction(add)
.then{ Log .d( " AndroidNativeInterface " , " Web calculated: ${add.a} + ${add.b} = $it " ) }
. catch { Log .e( " AndroidNativeInterface " , " ERROR IN WEB LAYER: $it " ) }
}
}
data class Add ( a : Int , b : Int )
} // Javascript
Bridge . interfaces . Android . registerOnClickAction ( ( add ) => {
return new Promise ( ( resolve ) => { resolve ( add . a + add . b ) } )
} )บันทึก
ในการปล่อย JSFunction และล้างการเชื่อมโยงเพียงเรียกใช้ฟังก์ชั่น close JSFunction ใช้อินเทอร์เฟซ AutoCloseable ซึ่งช่วยให้คุณใช้ประโยชน์จากทรัพยากรแบบ try-with-sources หรือ AutoCloseable.use {} บล็อกเพื่อจัดการวงจรชีวิตของฟังก์ชั่นโดยอัตโนมัติและตรวจสอบการทำความสะอาดที่เหมาะสม
function.use { it() } นอกจากนี้หากเว็บแอปพลิเคชันหรือ WebView ของคุณรองรับการโหลดซ้ำขอแนะนำให้เพิ่ม Afterinitializelistener ลงในสะพาน ผู้ฟังนี้จะช่วยปล่อย JSFunctions ที่มีอยู่เพื่อให้มั่นใจว่าสถานะที่สะอาดหลังจากเริ่มต้น
ไลบรารีนี้รองรับประเภทการโทรแบบเนทีฟที่แตกต่างกันซึ่งให้คุณตัดสินใจว่าจะเรียกรหัสดั้งเดิมได้อย่างไร
ประเภทการโทร CallType.FULL_SYNC ใช้รหัสเนทีฟในลักษณะการปิดกั้นทำให้การดำเนินการ JavaScript หยุดชั่วคราวจนกว่าฟังก์ชั่น Android ดั้งเดิมจะกลับมา เป็นผลให้มุมมองเว็บยังคงไม่ตอบสนองจนกว่าการดำเนินการดั้งเดิมจะเสร็จสมบูรณ์ (ไม่แนะนำสำหรับงานที่ใช้เวลานาน)
// Kotlin
@NativeCall( CallType . FULL_SYNC )
fun searchContact ( contactFilter : ContactFilter ): List < Contact > {
return contactService.search(contactFilter)
} // Javascript
console . log ( Bridge . interfaces . Android . searchContact ( { surname : "Pitt" } ) ) ฟังก์ชั่นประเภทการโทร CallType.WEB_PROMISE คล้ายกับการโทร FULL_SYNC โดยมีความแตกต่างที่สำคัญคือการเรียก JavaScript ส่งคืนสัญญา อย่างไรก็ตามฟังก์ชั่น Android ดั้งเดิมยังคงเรียกใช้ในลักษณะการปิดกั้น (แนะนำหากคุณไม่แน่ใจเกี่ยวกับระยะเวลาของงานและอาจจำเป็นต้องย้ายไปยัง FULL_PROMISE ในอนาคต)
// Kotlin
@NativeCall( CallType . WEB_PROMISE )
fun searchContact ( contactFilter : ContactFilter ): List < Contact > {
return contactService.search(contactFilter)
} // Javascript
Bridge . interfaces . Android . searchContact ( { surname : "Pitt" } ) . then ( ( list ) => {
console . log ( list ) ;
} ) ; ประเภทการโทร CallType.FULL_PROMISE ช่วยให้คุณสามารถเรียกใช้รหัส Android เนทีฟในเธรดพื้นหลังทำให้การดำเนินการ JavaScript สามารถดำเนินการต่อไปได้อย่างต่อเนื่อง เป็นผลให้มุมมองเว็บยังคงตอบสนองและมีอิสระในการปฏิบัติงาน (แนะนำสำหรับงานระยะยาว)
// Kotlin
@NativeCall( CallType . FULL_PROMISE )
fun searchContact ( contactFilter : ContactFilter ) = doInBackground< List < Contact >> { promise ->
try {
promise.resolve(contactService.search(contactFilter))
} catch (e : Exception ) {
promise.reject(e)
}
} // Javascript
Bridge . interfaces . Android . searchContact ( { surname : "Pitt" } ) . then ( ( list ) => {
console . log ( list ) ;
} ) ; เพิ่ม Maven Central ให้กับบล็อกที่เก็บ
repositories {
google()
mavenCentral()
}เพิ่มไลบรารีลงในบล็อกการพึ่งพา
dependencies {
implementation ' com.github.andycandy-de:simple-android-bridge:1.1.1 '
} class AndroidNativeInterface : DefaultJSInterface ( " Android " ) {
@NativeCall( CallType . FULL_SYNC )
fun helloFullSync ( name : String ): String {
return " hello $name "
}
@NativeCall( CallType . WEB_PROMISE )
fun helloWebPromise ( name : String ): String {
return " hello $name "
}
@NativeCall( CallType . FULL_PROMISE )
fun helloFullPromise ( name : String ) = doInBackground< String > { promise ->
promise.resolve( " hello $name " )
}
} val bridge = Bridge (applicationContext, webView)
bridge.addJSInterface( AndroidNativeInterface ())รหัส Android
// Bridge can be initialized by calling the 'init' function inside
// the 'onPageStarted' function of a WebViewClient
webView.webViewClient = object : WebViewClient () {
override fun onPageStarted ( view : WebView ? , url : String? , favicon : Bitmap ? ) {
bridge. init ()
}
}รหัส JavaScript
// Bridge can be initialized by calling the 'init' function in
// Javascript. Register function to 'Bridge.afterInitialize' to
// start the webapp after the bridge is initialized.
function startApp ( f ) {
if ( Bridge . initialized ) {
f ( )
} else {
Bridge . afterInitialize = f
}
}
Bridge . init ( )
startApp ( ( ) => {
// Start your webapp
} ) ; console . log ( Bridge . interfaces . Android . helloFullSync ( "Web" ) ) ใบอนุญาต MIT
ลิขสิทธิ์ (c) 2020 Andycandy-de
ลิขสิทธิ์ (c) 2021 Andycandy-de
ลิขสิทธิ์ (c) 2024 Andycandy-de
ได้รับอนุญาตโดยไม่ต้องเสียค่าใช้จ่ายสำหรับบุคคลใด ๆ ที่ได้รับสำเนาซอฟต์แวร์นี้และไฟล์เอกสารที่เกี่ยวข้อง ("ซอฟต์แวร์") เพื่อจัดการในซอฟต์แวร์โดยไม่มีการ จำกัด รวมถึง แต่ไม่ จำกัด เฉพาะสิทธิ์ในการใช้สำเนาดัดแปลงผสานเผยแพร่เผยแพร่
ประกาศลิขสิทธิ์ข้างต้นและประกาศการอนุญาตนี้จะรวมอยู่ในสำเนาทั้งหมดหรือส่วนสำคัญของซอฟต์แวร์
ซอฟต์แวร์มีให้ "ตามสภาพ" โดยไม่มีการรับประกันใด ๆ ไม่ว่าโดยชัดแจ้งหรือโดยนัยรวมถึง แต่ไม่ จำกัด เฉพาะการรับประกันความสามารถในการค้าการออกกำลังกายสำหรับวัตถุประสงค์เฉพาะและการไม่เข้าร่วม ไม่ว่าในกรณีใดผู้เขียนหรือผู้ถือลิขสิทธิ์จะต้องรับผิดชอบต่อการเรียกร้องความเสียหายหรือความรับผิดอื่น ๆ ไม่ว่าจะเป็นการกระทำของสัญญาการละเมิดหรืออื่น ๆ ที่เกิดขึ้นจากหรือเกี่ยวข้องกับซอฟต์แวร์หรือการใช้งานหรือการติดต่ออื่น ๆ ในซอฟต์แวร์