02 October 2016

ลองเล่น Quick Settings Tile API ของเล่นใหม่ใน Android 7.0 Nougat

Updated on


        เมื่อวันก่อนแอบไปส่องฟีเจอร์ใหม่ๆใน Android 7.0 Nougat ดูก็พบว่ามีฟีเจอร์ตัวหนึ่งที่น่าสนใจที่มีชื่อว่า Quick Settings Tile ก็เลยหยิบมาเล่าให้ฟังเล่นๆซะหน่ย

Quick Settings Tile

        Quick Settings นั้นเป็นฟีเจอร์ที่เพิ่มความสามารถให้กับ Notification Shade หรือแถบ Notification ซึ่งผู้ใช้ส่วนใหญ่ได้สัมผัสกันมาตั้งแต่สมัย Android 5.0 Lollipop แล้วล่ะ


        และในที่สุดก็เปิดให้นักพัฒนาสามารถ Custom เจ้า Quick Settings Tile ได้แล้ว เย้! โดยมีชื่อเรียกว่า Quick Settings Tile API นั่นเอง

แล้ว...มันใช้งานยังไงล่ะ?

        Quick Settings จะทำงานในรูปแบบของ Service โดยที่ Quick Settings นั้นจะมีคลาสที่ชื่อว่า Tile Service ให้ใช้งาน แบบนี้

import android.service.quicksettings.TileService;

public class AwesomeTileService extends TileService {

    ...

}


        และเวลาประกาศ Service ไว้ใน Android Manifest จะบังคับให้ประกาศ Permission สำหรับ Quick Settings ดังนี้

android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"


        การที่ระบบแอนดรอยด์จะรู้ได้ว่า Service ตัวนี้มีไว้แสดงใน Quick Settings Tile ก็จะมาจากการกำหนดค่าไว้ใน Intent Filter แบบนี้

<intent-filter>
    <action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>


        และสิ่งสุดท้ายใน Android Manifest ให้กำหนด android:icon กับ android:label ด้วย เพราะทั้งสองค่านี้จะถูกดึงไปแสดงเป็น Quick Settings นั่นเอง ดังนั้น Service ที่ประกาศไว้ใน Android Manifest จะเป็นแบบนี้

<?xml version="1.0" encoding="utf-8"?>
<manifest 
    ...>

    <application
        ...>

        ...

        <service
            android:name=".AwesomeTileService"
            android:icon="@drawable/ic_profile"
            android:label="@string/qs_tile_name"
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE" />
            </intent-filter>
        </service>
    </application>

</manifest>

        จากนั้นให้ลองทดสอบดูก่อนนะว่าทำงานได้หรือไม่




        สำหรับไอคอนที่สร้างขึ้นมาแสดงใน Quick Settings นี้จะขอเรียกว่า Tile นะ

มาดูกันต่อว่าทำอะไรกับ Quick Settings Tile ได้บ้าง

        สำหรับ Public Method ที่มีให้ Override จะมีดังนี้

import android.service.quicksettings.TileService;

public class QuickSettingService extends TileService {

    @Override
    public void onTileAdded() {
        ...
    }

    @Override
    public void onTileRemoved() {
        ...
    }

    @Override
    public void onStartListening() {
        ...
    }

    @Override
    public void onStopListening() {
        ...
    }

    @Override
    public void onClick() {
        ...
    }
}

        • onTileAdded : ทำงานก็ต่อเมื่อ Quick Settings ถูกเพิ่มเข้าไปใน Quick Settings Tile

        • onTileRemoved : ทำงานก็ต่อเมื่อ Quick Settings ถูกถอดออกจาก Quick Settings Tile

        • onStartListener : ทำงานก็ต่อเมื่อ Tile อยู่ในสถานะ Listening

        • onStopListener : ทำงานก็ต่อเมื่อ Tile ไม่ได้อยู่ในสถานะ Listening

        • onClick : ทำงานก็ต่อเมื่อผู้ใช้มีการกดเลือกที่ Tile ตัวนั้นๆ


      และ Public Method ที่มีให้เรียกใช้งาน (Override ไม่ได้) จะมีดังนี้

Tile getQsTile()
boolean isLocked()
boolean isSecure()
void requestListeningState(Context context, ComponentName component)
void showDialog(Dialog dialog)
void startActivityAndCollapse(Intent intent)
void unlockAndRun(Runnable runnable)

        • getQsTile : ดึงคลาส Tile เพื่อใช้ในการอ่าน/กำหนดค่าให้กับ Tile

        • isLocked : เช็คว่าอยู่ใน Lock Screen (เพราะ Quick Settings Tile สามารถแสดงในหน้า Lock Screen ได้)

        • isSecure : เช็คว่าเครื่องนั้นๆกำหนด Lock Screen เป็นแบบ Secure หรือไม่ (Pattern, Password และอื่นๆ ที่ไม่ใช่ None หรือ Swipe)

        • requestListeningState : เป็นการเรียก Listening State ของ Tile เพื่ออัพเดท

        • showDialog : แสดง Dialog พร้อมกับปิดหน้าต่าง Notification Shade ลง

        • startActivityAndCollapse : เปิด Activity พร้อมกับปิดหน้าต่าง Notification Shade ลง

        • unlockAndRun : ปลดล็อคหน้าจอและทำคำสั่งที่กำหนดไว้ใน Runnable

การทำงานของ Listening State

        Tile นั้นจะมี Listening State อยู่ 2 State ด้วยกันคือ Start กับ Stop เพื่อให้สามารถอัพเดทสถานะของตัว Tile ได้

        โดยปกติแล้ว Listening จะเริ่มทำงาน (Start) เมื่อ Tile ถูกแสดงให้เห็น แม้ว่าจะแค่เปิดหน้าต่าง Quick Settings Tile ก็ตาม และก็จะหยุดทำงาน (Stop) เมื่อ Tile ไม่แสดงให้ผู้ใช้เห็นแล้ว

        นอกจากนี้ยังกำหนดให้ Listening ทำงานในแบบ Active Mode ได้อีกด้วย โดยกำหนดใน Android Manifest ด้วย <meta-data> แบบนี้

<meta-data
    android:name="android.service.quicksettings.ACTIVE_TILE"
    android:value="true" />

<service
    android:name=".AwesomeTileService"
    android:icon="@drawable/ic_profile"
    android:label="@string/qs_tile_name"
    android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">

    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
    
    <meta-data
        android:name="android.service.quicksettings.ACTIVE_TILE"
        android:value="true" />
</service>

        เมื่ออยู่ใน Active Mode จะทำให้ Listening State เปลี่ยนไป โดยที่ Start จะไม่ทำงานในทันทีที่ Tile ถูกแสดงให้ผู้ใช้เห็น แต่ว่าจะทำงานก็ต่อเมื่อใช้คำสั่ง requestListeningState เท่านั้น

ComponentName componentName = new ComponentName(context, serviceClassName);
requestListeningState(this, componentName);

        แต่ว่า Listening ก็หยุดทำงานเมื่อ Tile หายไปจากหน้าจอเหมือนเดิมอยู่นะ

        และถ้าไม่ได้ประกาศ <meta-data> ดังกล่าวก็จะทำให้คำสั่ง requestListeningState ไม่มีผลใดๆ

การทำงานของ Unlock And Run

        อย่างที่บอกในตอนแรกว่า Quick Settings Tile นั้นสามารถแสดงในระหว่างอยู่หน้าจอ Lock Screen ได้ ดังนั้นจึงสามารถสั่งให้ Unlock หน้าจอได้

        แต่ทว่า Lock Screen ก็สามารถมีการใส่รหัสเพื่อปลดล็อคหน้าจอได้ ดังนั้นคำสั่ง unlockAndRun จะยังไม่ทำงานในทันที เพื่อรอให้ผู้ใช้ปลดล็อคหน้าจอเสร็จเสียก่อน และถ้าผู้ใช้ไม่ยอมปลดล็อคหน้าจอก็จะไม่ทำคำสั่งนั้นเช่นกัน

public class AwesomeTileService extends TileService {

    ...

    @Override
    public void onClick() {
        unlockAndRun(runnable);
    }

    public Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // TODO Do something
        }
    };
}

        ดังนั้นคำสั่ง unlockAndRun จึงต้องใช้ Runnable เพื่อกำหนดคำสั่งที่จะให้ทำงานหลังจากปลดล็อคหน้าจอแล้วนั่นเอง

คำสั่งต่างๆของ Tile

        สำหรับการกำหนดรูปแบบการแสดงผลของ Tile นั้นจะไม่ได้อยู่ในคลาส TileService โดยตรง แต่จะมีคลาส Tile สำหรับกำหนดอีกทีหนึ่ง ซึ่ง Tile สามารถดึงได้จากคำสั่ง getQsTile

Tile tile = getQsTile();

        และคำสั่งที่มีให้ใช้งานใน Tile จะมีดังนี้

void setIcon(Icon icon)
void setLabel(CharSequence label)
void setState(int state)
void setContentDescription(CharSequence contentDescription)
void updateTile()
Icon getIcon()
int getState()
CharSequence getLabel()
CharSequence getContentDescription()

        • setIcon : กำหนดภาพที่จะใช้แสดงใน Tile

        • setLabel : กำหนดข้อความที่จะใช้แสดงใน Tile

        • setState : กำหนดสถานะของ Tile

        • setContentDescription : กำหนด Content Description ของ Tile

        • updateTile : อัพเดทค่าทั้งหมดของ Tile

        • getIcon : ดึงภาพที่ใช้แสดงใน Tile

        • getState : ดึงสถานะของ Tile

        • getLabel : ดึงข้อความที่ใช้แสดงใน Tile

        • getContentDescription : ดึง Content Description ของ Tile

การกำหนดค่าต่างๆให้กับ Tile

        สำหรับการกำหนด Label ให้กับ Tile ก็เป็นแค่ CharSequence ธรรมดาๆไม่มีอะไรซับซ้อน



        สำหรับการกำหนดค่า Icon จะต้องกำหนดค่าด้วยคลาส Icon แบบนี้

Icon icon = Icon.createWithResource(this, R.drawable.avatar);
getQsTile().setIcon(icon);

        โดยที่คลาส Icon สามารถดึงภาพได้หลายๆรูปแบบไม่ว่าจะเป็น Drawable, Bitmap, Uri, File หรือแม้แต่ Byte Array ก็ตาม

        แต่ภาพที่ใช้ใน Tile จะถูกทำให้เป็นสีขาวทั้งหมด ดังนั้นเลี่ยงการใช้ภาพที่เป็นหลากสี ควรใช้ภาพที่เป็นแบบไอคอนแทน (พื้นหลังโปร่งใส และเป็นสีโทนเดียว)



        สำหรับการกำหนดสถานะของ Tile จะมีอยู่ด้วยกัน 3 สถานะดังนี้

Tile.STATE_ACTIVE
Tile.STATE_INACTIVE
Tile.STATE_UNAVAILABLE

        • Active สถานะที่บ่งบอกว่า Tile กำลังทำงานอยู่ (Active)

        • Inactive สถานะที่บ่งบอกว่า Tile ไม่ได้ทำงาน (Inactive)

        • Unavailable สถานะที่บ่งบอกว่า Tile ไม่สามารถใช้งานหรือทำงานได้


        สำหรับสถานะ Active และ Inactive ผู้ใช้สามารถกดแล้วเข้า Event ที่ชื่อว่า onClick ได้ แต่สำหรับกรณีของสถานะ Unavailable จะไม่เกิดอะไรขึ้น จึงมีไว้สำหรับกำหนดเมื่อบางอย่างไม่สามารถทำงานได้เลย (เช่น Tile สำหรับสถานะ Bluetooth แต่ทว่าเครื่องนั้นไม่มี Bluetooth จึงไม่สามารถใช้งาน Tile ตัวนี้ได้)

        และเมื่อกำหนดค่าต่างๆ จะยังไม่มีผลทันที จนกว่าจะเรียกคำสั่ง updateTile

Tile tile = getQsTile();
tile.setState(Tile.STATE_INACTIVE);
tile.setLabel(getString(R.string.qs_inactive_label));
getQsTile().setState(Tile.STATE_ACTIVE);
getQsTile().updateTile();

การประยุกต์ใช้งาน

        สุดท้ายนี้ก็ขึ้นอยู่กับว่าจะเอาไปประยุกต์ใช้งานกับแอปฯต่างๆยังไงแล้วล่ะ เพราะการเปิด Quick Settings Tile API นั้นจะช่วยเพิ่มความสามารถของแอปฯได้หรือไม่ก็ขึ้นอยู่กับว่าแอปฯตัวนั้นๆเป็นแบบไหน ในกรณีที่เป็นแอพที่เป็นแอปฯที่ต้องใช้การบ่อยๆ มีการเปิด/ปิดการทำงานบางอย่างของแอปฯอยู่เป็นประจำ ก็จะเหมาะมากๆที่ทำ Quick Settings Tile เพื่อให้ผู้ใช้งานสามารถใช้งานได้สะดวกยิ่งขึ้น


        แต่อย่างน้อยก็สามารถทำแบบนี้ได้นะ ฮาๆ

แหล่งข้อมูลอ้างอิง

        • Quick Settings Tile API [Android Developer]

        • TileService [API Reference]

        • Tile [API Reference]