วันศุกร์ที่ 29 มีนาคม พ.ศ. 2562

GPS Accuracy

    ในช่วงสัปดาห์ที่ผ่านมานั้นได้มีคำแนะนำเกี่ยวกับการหาค่าความคลาดเคลื่อนของระบบ GPS โดยเราสามารถใช้ค่าของ Accuracy มาช่วยในการระบุเกี่ยวกับค่าความคลาดเคลื่อนได้ ดังรูปข้างล่าง


    ในรูปด้านบนได้บอกว่าเราได้ค่าความคลาดเคลื่อนมีค่าเท่ากับ 2 ซึ่งจากการเดินสำรวจ ได้พบว่าค่าความคลาดเคลื่อนดังกล่าวนั้นมีแค่ค่า 1-3 เท่านั้น เลยเกิดข้อสงสัยว่าค่าที่ได้นั้นมีความถูกต้องหรือเปล่า ก็เลยไปค้นคว้าในตัวเอกสาร ปรากฏว่าค่าที่ได้นั้นเป็นค่าระดับ 1 - 3 (High Mid Low) ซึ่งเป็นผลจากการใช้ SDK Wikitude 

    วิธีแก้ไขคือเราได้ใช้ API ของ Android ส่งค่าให้แสดงค่าโดยตรงซึ่งจะได้มาเป็นค่าดังรูปด้านล่าง













    โดยเลข 22 เมตรนั้นหมายถึงมีค่าความผิดพลาดของตัว GPS อยู่ที่ 22 เมตรเป็นรัศมีวงกลม คล้ายๆกับของเวลาเราใช้ Google Maps

    

วันศุกร์ที่ 22 มีนาคม พ.ศ. 2562

ข้อจำกัดเรื่อง WiFi ของ Android 9 (หรือเวอร์ชั่นที่ใหม่กว่า)

    เนื่องจากในขณะที่กำลังทดสอบการตรวจจับข้อมูลสัญญาณ WiFi พบว่ามือถือของผมนั้น (Xiaomi Mi A1, Android 9) มีการอัพเดทข้อมูลเพียงเล็กน้อยแล้วนิ่งไปสักพักจึงจะมีการอัพเดทข้อมูลอีกครั้ง ส่วนมือถือของธนัท (Asus Zenfone Max Pro M2, Android 8.1) กลับอัพเดทข้อมูลได้เรื่อยๆไม่มีปัญหาอะไร ผมจึงได้ทำการหาข้อมูลว่าปัญหาเกิดจากอะไร จนพบว่า


    ฟังก์ชั่น startScan() ซึ่งใช้สำหรับ trigger ให้อุปกรณ์ทำการ Scan WiFi เพื่ออัพเดทข้อมูล ถูกเลิกใช้ตั้งแต่ API level 28 (Android 9) ขึ้นไป และมีการจำกัดจำนวนครั้งการสแกน โดยจะสามารถสแกนได้ 4 ครั้งใน 2 นาทีสำหรับ Foreground Application และ 1 ครั้งใน 30 นาที สำหรับ Background Application

    ซึ่งการยกเลิกฟังก์ชั่นดังกล่าวทำให้ Developer ที่ทำ Application ที่เกี่ยวกับ indoor maps และ wifi analyzer พบกับปัญหากัน ซึ่งทางออกที่ Google แนะนำคือให้ใช้ WifiRttManager แทน แต่ก็มีข้อจำกัดคือ อุปกรณ์ทั้งมือถือ และ Access Point จะต้องรองรับมาตรฐาน wifi IEEE 802.11mc ซึ่งอุปกรณ์ที่รองรับตอนนี้ยังมีไม่มากนัก


แนวทางการแก้ปัญหา

    อาจจะต้องจำกัดให้สามารถใช้ได้แค่ Android 8.1 ลง



แหล่งอ้างอิง

วันอังคารที่ 5 มีนาคม พ.ศ. 2562

การติดต่อกันระหว่าง Java และ JavaScript


    โดยปกติแล้วการสร้างแอปพลิเคชั่น android จะเขียนด้วยภาษา Java แต่ในโปรเจค AR Navigator ของเรานั้นมีการใช้ Wikitude JavaScript API ทำให้ในโปรเจคนี้จะมีการใช้ภาษาโปรแกรมมิ่ง 2 ภาษา คือ Java และ JavaScript โดยจะแบ่งหน้าที่กันดังนี้
  • JavaScript (HTML, CSS, Jquery Mobile, etc.) ใช้สำหรับสร้างแอป AR และระบบการทำงานโดยส่วนใหญ่ของแอปพลิเคชั่น
  • Java จะเรียกใช้แอปที่สร้างด้วย JS มาแสดงผล และระบบการทำงานที่เกี่ยวกับ Hardware เช่น ตั้งค่าความละเอียดกล้อง, การเรียกใช้ GPS
ภาพตัวอย่าง คำสั่งการเรียกใช้แอปที่สร้างด้วย JS เพื่อมาแสดงผล


การส่งค่า GPS จาก Java ไปสู่ JavaScript

    ใน Java เราจะใช้คำสั่งจาก Library ของ Wikitude คือ ArchitectView.setLocation() เพื่อเซ็ตค่าบอกให้ Wikitude API รู้ว่าเรากำลังอยู่ที่ตำแหน่งไหน
    ส่วนใน JavaScript ก็จะมีฟังก์ชั่น AR.context.onLocationChanged() ที่จะถูกเรียกอัตโนมัติเมื่อค่าตำแหน่งใน Wikitude API มีการเปลี่ยนแปลง วิธีใช้คือให้ทำการ override ฟังก์ชั่นนี้แล้วทำการเพิ่ม statement ที่ต้องการลงไป


Java เรียกใช้ฟังก์ชั่นของ JavaScript ได้

    โดยใช้คำสั่ง architectView.callJavascript("") เช่น จะเรียกใช้ฟังก์ชั่น resetDropdown ก็จะใช้คำสั่ง architectView.callJavascript("resetDropdown()") เป็นต้น ซึ่งคำสั่งนี้จะสามารถเรียกใช้ฟังก์ชั่นของ JS ได้อย่างเดียว ไม่สามารถที่จะรับค่าจะฟังก์ชั่นที่มีการ return ค่าได้


JavaScript ไม่สามารถเรียกใช้ฟังก์ชั่น Java ได้ แต่สามารถส่ง JSON Object ให้ Java ได้

    โดยจะส่งค่าผ่านคำสั่ง AR.platform.sendJSONObject() ใน JavaScript ส่วนใน Java จะต้องทำการเรียกใช้ ArchitectView.addArchitectJavaScriptInterfaceListener(this); ก่อน ซึ่งควรเรียกใช้ใน onCreate() เพื่อจะได้เรียกใช้ตั้งแต่เปิดแอปพลิเคชั่น และควรใส่ ArchitectView.removeArchitectJavaScriptInterfaceListener(this); ไว้ใน onDestroy() เพื่อที่จะ remove listener ออกเมื่อปิดแอป
    การรับค่าที่ JavaScript ส่งมาสามารถทำได้โดยการ override ฟังก์ชั่น onJSONObjectReceived() ใน Java ที่จะถูกเรียกใช้ทุกคร้ังเมื่อมีการส่ง JSON Object มา

    ตัวอย่างการใช้งาน
         ต้องการจะส่งค่า State จาก JS มาเก็บไว้ที่ Java โดยใช้คำสั่ง AR.platform.sendJSONObject({action: "sendState", state: "home"}); ก็จะทำการ override ฟังก์ชั่น onJSONObjectReceived() ออกมาได้ดังนี้


        สาเหตุที่ต้องส่ง action มา และ override onJSONObjectReceived() ออกมาเป็นรูปแบบของ Switch-Case ก็เพราะเผื่อในอนาคตเราต้องการที่จะส่งค่า JSON Object อย่างอื่นที่ไม่เกี่ยวกับเรื่อง state เข้ามาก็จะได้แบ่งการทำงานแยกกันได้

การส่งเรื่องขอใช้ Wikitude Startup

    จากในโพสต์ที่ผ่านมาเรื่องปัญหาของการอัพโหลด App ของเราขึ้นไปบน App Store นั้นติดปัญหาเรื่อง License ของ Wikitude SDK ที่เป็นเวอร์ชั่น EDU โดยมีข้อจำกัดที่ว่าเราไม่สามารถทำการเผยแพร่ App ของเราผ่านทาง App Store ใดๆได้ทำให้เราจำเป็นจะต้องหาวิธีอื่นในการเผยแพร่ App

    ทางเลือกอื่นที่น่าสนใจคือการเปลี่ยนตัว License จากที่ใช้เวอร์ชั่น EDU ไปใช้เป็นของ Startup แทนซึ่งผมได้ทำการใส่กรอกแบบฟอร์มเพื่อขอใช้งานตัว License Startup ไปแล้วซึ่งทาง Wikitude ก็ได้ส่งเมล์ตอบรับกลับมาว่าข้อมูลที่ส่งไปตรงตามเกณฑ์สามารถใช้งาน License Startup ของเขาได้ และขอให้ผมส่งชื่อ package name ของ App เพื่อให้เขาทำการสร้าง License แล้วส่งมาให้เราใช้งาน

    ในวันที่เขียนโพสต์นี้นั้นคือวันที่ 5 มีนาคม 2562 ซึ่งผมได้ส่ง package name ที่ต้องการไปตั้งแต่วันที่ 1 มีนาคม 2562 ยังไม่มีการตอบกลับมาซึ่งถ้าได้ผลลัพธ์อย่างไรจะมาอัพเดทอีกรอบครับผม