บทความนี้เก่ามากแล้ว และหยุดพัฒนาต่อแล้ว
สำหรับผู้ที่หลงเข้ามาอ่านคนใดยังไม่รู้จักกับคลาสนี้ให้ไปศึกษาก่อนที่ [Android Code] เปลี่ยนเรื่องบลูทูธให้เป็นเรื่องง่ายด้วย BluetoothSPP Library และถ้ายังไม่รู้จักการใช้งานเบื้องต้นให้ไปศึกษาก่อนที่ [Android Code] การเชื่อมต่ออุปกรณ์ผ่านบลูทูธแบบง่ายๆโดยใช้ BluetoothSPP
คราวนี้จะมาพูดถึงการใช้งาน Listener ที่อยู่ในคลาส BluetoothSPP กันบ้าง โดยคลาส BluetoothSPP เจ้าของบล็อกได้ใส่ Listener ต่างๆไว้จำนวนหนึ่งเพื่ออำนวยความสะดวกในการใช้งาน ซึ่งจะมีทั้งหมดดังนี้
• BluetoothConnectionListener
เป็น Listener ที่เอาไว้คอยตรวจจับการเชื่อมต่อบลูทูธ เพื่อให้ผู้นำไปใช้งานสามารถตรวจสอบจากตรงนี้ได้เลยว่า เชื่อมต่อบลูทูธได้แล้วหรือยัง? การเชื่อมต่อล้มเหลวหรือป่าว? มีการยกเลิกการเชื่อมต่อ? โดยจะมีเมธอดภายในอยู่ 3 เมธอดด้วยกัน คือ
onDeviceConnected
เมธอดนี้จะทำงานก็ต่อเมื่อการเชื่อมต่อสำเร็จ โดยจะมีพารามิเตอร์ด้วยกันสองตัวคือ String ที่เป็นชื่อของอุปกรณ์ที่เชื่อมต่อ และ String ที่เป็น Address ของอุปกรณ์ที่เชื่อมต่อ เอาไว้แสดงให้ผู้ใช้เห็นได้ว่าทำการเชื่อมต่อได้แล้ว และเชื่อมต่อกับอุปกรณ์อะไร
onDeviceDisconnected
เมธอดนี้จะทำงานก็ต่อเมื่ออยู่ในขณะกำลังเชื่อมต่ออยู่ แล้วมีการยกเลิกการเชื่อมต่อ
onDeviceConnectionFailed
เมธอดนี้จะทำงานก็ต่อเมื่อกำลังทำการเชื่อมต่อแล้วการเชื่อมต่อล้มเหลว
• OnDataReceivedListener
เป็น Listener ที่เอาไว้คอยตรวจจับการรับข้อมูลที่ส่งเข้ามาทางบลูทูธ โดยจะมีเมธอดภายในแค่ตัวเดียว คือ
onDataReceived
เมธอดนี้จะทำงานก็ต่อเมื่ออุปกรณ์ที่เชื่อมต่อนั้นมีการส่งข้อมูลเข้ามา โดยจะมีพารามิเตอร์ด้วยกันสองตัวคือ Byte Array ซึ่งเป็นข้อมูลที่ส่งเข้ามาที่อยู่ในรูปของ Byte เพื่อใช้ในกรณีที่ข้อมูลที่ส่งเข้ามาไม่ได้อยู่ในรูป ASCII และพารามิเตอร์อีกตัวคือ String ที่เป็นข้อมูลที่ส่งเข้ามาที่อยู่ในรูป ASCII String
โดยทั้งสองพารามิเตอร์นี้มีจุดประสงค์การใช้งานไม่เหมือนกัน ถ้านำไปใช้งานรับส่งข้อมูล Byte ที่ต้องนำไปใช้งานอีกทอดหนึ่ง ก็ควรใช้ข้อมูลแบบ Byte Array แต่ถ้าส่งข้อมูลเป็นแบบข้อความ ASCII ก็ควรใช้ข้อมูลแบบ String
• AutoConnectionListener
เป็น Listener ที่เอาไว้ตรวจจับการทำงานของระบบเชื่อมต่อบลูทูธแบบอัตโนมัติที่เจ้าของบล็อกเขียนไว้ เพื่อให้ผู้ที่นำไปใช้งานสามารถตรวจสอบได้ว่าระบบเชื่อมต่ออัตโนมัติกำลังเชื่อมต่อกับอุปกรณ์ตัวไหนอยู่บ้าง แต่จะไม่มีบอกว่าเชื่อมต่อสำเร็จหรือไม่ เพราะว่าสามารถใช้ร่วมกับ BluetoothConnectionListener ได้ จึงไปตรวจสอบที่ Listener นั้นแทน โดย AutoConnectionListener จะมีเมธอดภายในอยู่ 2 ตัวด้วยกัน คือ
onNewConnection
เมธอดนี้จะทำงานเมื่อการเชื่อมต่ออัตโนมัติกำลังทำการเชื่อมต่อกับอุปกรณ์ตัวถัดไป สมมติเช่น มีรายชื่ออุปกรณ์อยู่ในเครื่องทั้งหมด 3 ชื่อด้วยกัน เมื่อเริ่มเชื่อมต่อตัวแรก เมธอดนี้ก็จะทำงาน ถ้าเชื่อมต่อไม่สำเร็จก็จะไปเชื่อมต่อตัวถัดไปแทน เมธอดนี้ก็จะทำงานอีกครั้ง ไปเรื่อยๆตลอดการเชื่อมต่ออัตโนมัติจนกว่าจะเชื่อมต่อกับอุปกรณ์ตัวใดๆได้
โดยจะมีพารามิเตอร์อยู่ด้วยกันสองตัวคือ String ที่เป็นชื่อและ Address ของอุปกรณ์ที่ทำการเชื่อมต่อ ซึ่งคล้ายๆกับ onDeviceConnected เลย (แต่อันนั้นเป็นกรณีที่เชื่อมต่อสำเร็จแล้ว)
onAutoConnectionStarted
เมธอดนี้ไม่มีอะไรมาก จะทำงานก็ต่อเมื่อการเชื่อมต่ออัตโนมัติเริ่มทำงานเท่านั้นแหละ ใส่ไว้เผื่อว่ามีผู้ที่หลงเข้ามาอ่านคนใดต้องการจะใช้งาน
• BluetoothStateListener
เป็น Listener ที่เอาไว้ตรวจจับสถานะการทำงานของ Service ของบลูทูธว่ากำลังอยู่ในสถานะใด เพราะว่าการทำงานของ Service ของบลูทูธใน BluetoothSPP จะมีสถานะต่างๆด้วยกันดังนี้
None : Service ยังไม่ได้ทำอะไร
Listener : อยู่ในสถานะรอการเชื่อมต่อ
Connecting : กำลังทำการเชื่อมต่อ
Connected : เชื่อมต่อกับอุปกรณ์ใดๆอยู่
Null : Service ยังไม่ได้ถูกสร้างขึ้นมา
สถานะเหล่านี้จะอยู่ในคลาส BluetoothState ที่เจ้าของบล็อกได้เขียนเอาไว้แล้ว ดังนั้นเวลาตรวจสอบว่าอยู่ในสถานะอะไรก็ให้เทียบกับตัวแปรที่อยู่ในคลาสนี้ได้เลย (เดี๋ยวดูตัวอย่างอีกทีนึง)
โดยที่ BluetoothStateListener จะมีเมธอดอยู่ภายในเพียง 1 เมธอดเท่านั้น คือ
onServiceStateChanged
เมธอดนี้จะทำงานก็ต่อเมื่อ Service มีการเปลี่ยนสถานะการทำงาน โดยมีพารามิเตอร์เป็น Integer บอกให้รู้ว่าอยู่ในสถานะใด โดยต้องไปเทียบกับตัวแปรที่อยู่ในคลาส BluetoothState (วิธีใช้งานรอดูตัวอย่างในตอนท้าย)
การประกาศใช้งาน Listener เหล่านี้ก็ประกาศแบบ Anonymous ได้เลย หรือจะ Implement หรือจะประกาศเป็น Object ก็แล้วแต่ แต่เจ้าของบล็อกแบบ Anonymous เพราะชอบกระชับโค๊ดให้สั้นๆ
BluetoothSPP bt = new BluetoothSPP(this);
bt.setBluetoothStateListener(new BluetoothStateListener() {
public void onServiceStateChanged(int state) {
if(state == BluetoothState.STATE_CONNECTED)
Log.i("Check", "State : Connected");
else if(state == BluetoothState.STATE_CONNECTING)
Log.i("Check", "State : Connecting");
else if(state == BluetoothState.STATE_LISTEN)
Log.i("Check", "State : Listen");
else if(state == BluetoothState.STATE_NONE)
Log.i("Check", "State : None");
}
});
bt.setOnDataReceivedListener(new OnDataReceivedListener() {
public void onDataReceived(byte[] data, String message) {
Log.i("Check", "Message : " + message);
}
});
bt.setBluetoothConnectionListener(new BluetoothConnectionListener() {
public void onDeviceConnected(String name, String address) {
Log.i("Check", "Device Connected!!");
}
public void onDeviceDisconnected() {
Log.i("Check", "Device Disconnected!!");
}
public void onDeviceConnectionFailed() {
Log.i("Check", "Unable to Connected!!");
}
});
bt.setAutoConnectionListener(new AutoConnectionListener() {
public void onNewConnection(String name, String address) {
Log.i("Check", "New Connection - " + name + " - " + address);
}
public void onAutoConnectionStarted() {
Log.i("Check", "Auto connection started");
}
});
โดยเจ้าของบล็อกแนะนำให้ใช้คำสั่งไว้ใน onCreate เลย ต่อจากที่ประกาศ BluetoothSPP เป็นที่เรียบร้อยแล้ว
ทีนี้ก็ขอยกตัวอย่างการใช้งาน Listener ทั้ง 4 ตัวนี้เลย โดยตอนทดสอบอาจจะไม่เห็นผลการทำงานมากนัก แต่จะยกตัวอย่างวิธีเรียกใช้งานในคำสั่งให้ดูเป็นหลัก ส่วนจะเอาอันไหนไปใช้ก็แล้วแต่งานของผู้ที่หลงเข้ามาอ่าน เพราะไม่จำเป็นต้องเรียกใช้ทั้งหมดนี้ก็ได้
ส่วนการทำงานโดยรวมเบื้องต้นให้ศึกษาจากบทความนี้แทน [Android Code] การเชื่อมต่ออุปกรณ์ผ่านบลูทูธแบบง่ายๆโดยใช้ BluetoothSPP เพราะในบทความนี้เจ้าของบล็อกตัดคำสั่งบางอย่างที่ไม่จำเป็นมากนักออก เพราะว่าต้องการให้เห็นภาพรวมของวิธีประกาศใช้งาน Listener เท่านั้น
Main.java
package app.akexorcist.bluetoothspplistener;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import app.akexorcist.bluetoothspp.BluetoothSPP;
import app.akexorcist.bluetoothspp.BluetoothSPP.BluetoothStateListener;
import app.akexorcist.bluetoothspp.BluetoothSPP.OnDataReceivedListener;
import app.akexorcist.bluetoothspp.BluetoothState;
import app.akexorcist.bluetoothspp.DeviceList;
import app.akexorcist.bluetoothspp.BluetoothSPP.AutoConnectionListener;
import app.akexorcist.bluetoothspp.BluetoothSPP.BluetoothConnectionListener;
public class Main extends Activity {
BluetoothSPP bt;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt = new BluetoothSPP(this);
if(!bt.isBluetoothAvailable()) {
Toast.makeText(getApplicationContext(), "Bluetooth is not available"
, Toast.LENGTH_SHORT).show();
finish();
}
bt.setBluetoothStateListener(new BluetoothStateListener() {
public void onServiceStateChanged(int state) {
if(state == BluetoothState.STATE_CONNECTED)
Log.i("Check", "State : Connected");
else if(state == BluetoothState.STATE_CONNECTING)
Log.i("Check", "State : Connecting");
else if(state == BluetoothState.STATE_LISTEN)
Log.i("Check", "State : Listen");
else if(state == BluetoothState.STATE_NONE)
Log.i("Check", "State : None");
}
});
bt.setOnDataReceivedListener(new OnDataReceivedListener() {
public void onDataReceived(byte[] data, String message) {
Log.i("Check", "Message : " + message);
}
});
bt.setBluetoothConnectionListener(new BluetoothConnectionListener() {
public void onDeviceConnected(String name, String address) {
Log.i("Check", "Device Connected!!");
}
public void onDeviceDisconnected() {
Log.i("Check", "Device Disconnected!!");
}
public void onDeviceConnectionFailed() {
Log.i("Check", "Unable to Connected!!");
}
});
bt.setAutoConnectionListener(new AutoConnectionListener() {
public void onNewConnection(String name, String address) {
Log.i("Check", "New Connection - " + name + " - " + address);
}
public void onAutoConnectionStarted() {
Log.i("Check", "Auto connection started");
}
});
Button btnConnect = (Button)findViewById(R.id.btnConnect);
btnConnect.setOnClickListener(new OnClickListener(){
public void onClick(View v){
if(bt.getServiceState() == BluetoothState.STATE_CONNECTED) {
bt.disconnect();
} else {
Intent intent = new Intent(Main.this, DeviceList.class);
startActivityForResult(intent, BluetoothState.REQUEST_CONNECT_DEVICE);
}
}
});
}
public void onDestroy() {
super.onDestroy();
bt.stopService();
}
public void onStart() {
super.onStart();
if(!bt.isBluetoothEnabled()) {
bt.enable();
} else {
if(!bt.isServiceAvailable()) {
bt.setupService();
bt.startService(BluetoothState.DEVICE_ANDROID);
setup();
}
}
}
public void onActivityResult(int requestCode, int resultCode
, Intent data) {
if(requestCode == BluetoothState.REQUEST_CONNECT_DEVICE) {
if(resultCode == Activity.RESULT_OK)
bt.connect(data);
} else if(requestCode == BluetoothState.REQUEST_ENABLE_BT) {
if(resultCode == Activity.RESULT_OK) {
bt.setupService();
} else {
Toast.makeText(getApplicationContext(), "Bluetooth was not enabled."
, Toast.LENGTH_SHORT).show();
finish();
}
}
}
public void setup() { }
}
ส่วน Layout ก็จะไม่มีอะไร มีแค่ปุ่มเอาไว้เลือกอุปกรณ์ที่จะเชื่อมต่อเท่านั้น
main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/btnConnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Connect" />
</RelativeLayout>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.akexorcist.bluetoothspplistener"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="app.akexorcist.bluetoothspplistener.Main"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
จากนั้นก็ให้ลองทดสอบตามเงื่อนไขของ Listener แต่ละตัวดู แล้วเช็คที่ LogCat ก็จะเห็นข้อความขึ้นตามที่กำหนดไว้ แต่สำหรับบาง Listener อย่าง AutoConnectionListener อาจจะไม่เห็นผลลัพธ์ เพราะว่าไม่ได้เปิดใช้งานเชื่อมต่ออัตโนมัติ ซึ่งจะมีอธิบายในบทความของ Auto Connection อีกทีหนึ่ง
สำหรับผู้ที่หลงเข้ามาอ่านคนใดต้องการไฟล์ตัวอย่างสามารถดาวน์โหลดได้จาก
BluetoothSPP Listener [GitHub]
BluetoothSPP Listener [Google Drive]
BluetoothSPP Listener [Sleeping For Less]
บทความที่เกี่ยวข้อง
• เปลี่ยนเรื่องบลูทูธให้เป็นเรื่องง่ายด้วย BluetoothSPP Library
• การเชื่อมต่ออุปกรณ์ผ่านบลูทูธแบบง่ายๆโดยใช้ BluetoothSPP
• การใช้งานการเชื่อมต่ออัตโนมัติในคลาส BluetoothSPP
• การสร้างหน้าเลือกอุปกรณ์ที่จะเชื่อมต่อสำหรับ BluetoothSPP