একটি BLE ডিভাইসের সাথে ইন্টারঅ্যাক্ট করার প্রথম ধাপ হল এটির সাথে সংযোগ করা। আরও নির্দিষ্টভাবে, ডিভাইসে GATT সার্ভারের সাথে সংযোগ করা। একটি BLE ডিভাইসে একটি GATT সার্ভারের সাথে সংযোগ করতে, connectGatt()
পদ্ধতি ব্যবহার করুন। এই পদ্ধতিতে তিনটি পরামিতি লাগে: একটি Context
বস্তু, autoConnect
(একটি বুলিয়ান নির্দেশ করে যে এটি উপলব্ধ হওয়ার সাথে সাথে BLE ডিভাইসের সাথে স্বয়ংক্রিয়ভাবে সংযুক্ত হবে কিনা), এবং একটি BluetoothGattCallback
এর একটি রেফারেন্স :
কোটলিন
var bluetoothGatt: BluetoothGatt? = null ... bluetoothGatt = device.connectGatt(this, false, gattCallback)
জাভা
bluetoothGatt = device.connectGatt(this, false, gattCallback);
এটি BLE ডিভাইস দ্বারা হোস্ট করা GATT সার্ভারের সাথে সংযোগ করে এবং একটি BluetoothGatt
উদাহরণ প্রদান করে, যা আপনি GATT ক্লায়েন্ট অপারেশন পরিচালনা করতে ব্যবহার করতে পারেন। কলকারী (অ্যান্ড্রয়েড অ্যাপ) হল GATT ক্লায়েন্ট। BluetoothGattCallback
ব্যবহার করা হয় ক্লায়েন্টকে ফলাফল প্রদান করার জন্য, যেমন সংযোগের অবস্থা, সেইসাথে আরও GATT ক্লায়েন্ট অপারেশন।
একটি আবদ্ধ পরিষেবা সেট আপ করুন
নিম্নলিখিত উদাহরণে, BLE অ্যাপটি ব্লুটুথ ডিভাইসের সাথে সংযোগ করতে, ডিভাইসের ডেটা প্রদর্শন করতে এবং ডিভাইস দ্বারা সমর্থিত GATT পরিষেবা এবং বৈশিষ্ট্যগুলি প্রদর্শন করার জন্য একটি কার্যকলাপ ( DeviceControlActivity
) প্রদান করে। ব্যবহারকারীর ইনপুটের উপর ভিত্তি করে, এই কার্যকলাপটি BluetoothLeService
নামক একটি Service
সাথে যোগাযোগ করে, যা BLE API এর মাধ্যমে BLE ডিভাইসের সাথে যোগাযোগ করে। যোগাযোগ একটি আবদ্ধ পরিষেবা ব্যবহার করে সঞ্চালিত হয় যা কার্যকলাপটিকে BluetoothLeService
এর সাথে সংযোগ করতে এবং ডিভাইসগুলির সাথে সংযোগ করার জন্য ফাংশনগুলিকে কল করার অনুমতি দেয়৷ BluetoothLeService
একটি Binder
বাস্তবায়ন প্রয়োজন যা কার্যকলাপের জন্য পরিষেবাতে অ্যাক্সেস প্রদান করে।
কোটলিন
class BluetoothLeService : Service() { private val binder = LocalBinder() override fun onBind(intent: Intent): IBinder? { return binder } inner class LocalBinder : Binder() { fun getService() : BluetoothLeService { return this@BluetoothLeService } } }
জাভা
class BluetoothLeService extends Service { private Binder binder = new LocalBinder(); @Nullable @Override public IBinder onBind(Intent intent) { return binder; } class LocalBinder extends Binder { public BluetoothLeService getService() { return BluetoothLeService.this; } } }
কার্যকলাপটি bindService()
ব্যবহার করে পরিষেবাটি শুরু করতে পারে, পরিষেবাটি শুরু করার জন্য একটি Intent
পাস করে, সংযোগ এবং সংযোগ বিচ্ছিন্ন ঘটনাগুলি শোনার জন্য একটি ServiceConnection
বাস্তবায়ন এবং অতিরিক্ত সংযোগের বিকল্পগুলি নির্দিষ্ট করার জন্য একটি পতাকা।
কোটলিন
class DeviceControlActivity : AppCompatActivity() { private var bluetoothService : BluetoothLeService? = null // Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> // call functions on service to check connection and connect to devices } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.gatt_services_characteristics) val gattServiceIntent = Intent(this, BluetoothLeService::class.java) bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE) } }
জাভা
class DeviceControlActivity extends AppCompatActivity { private BluetoothLeService bluetoothService; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { // call functions on service to check connection and connect to devices } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } }; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE); } }
ব্লুটুথ অ্যাডাপ্টার সেট আপ করুন
একবার পরিষেবাটি আবদ্ধ হয়ে গেলে, এটিকে BluetoothAdapter
অ্যাক্সেস করতে হবে৷ ডিভাইসে অ্যাডাপ্টার উপলব্ধ আছে কিনা তা পরীক্ষা করা উচিত। BluetoothAdapter
সম্পর্কে আরও তথ্যের জন্য ব্লুটুথ সেট আপ করুন পড়ুন। নিম্নলিখিত উদাহরণটি এই সেটআপ কোডটিকে একটি initialize()
ফাংশনে মোড়ানো হয় যা সাফল্য নির্দেশ করে একটি Boolean
মান প্রদান করে।
কোটলিন
private const val TAG = "BluetoothLeService" class BluetoothLeService : Service() { private var bluetoothAdapter: BluetoothAdapter? = null fun initialize(): Boolean { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() if (bluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter.") return false } return true } ... }
জাভা
class BluetoothLeService extends Service { public static final String TAG = "BluetoothLeService"; private BluetoothAdapter bluetoothAdapter; public boolean initialize() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } return true; } ... }
কার্যকলাপটি এই ফাংশনটিকে তার ServiceConnection
বাস্তবায়নের মধ্যে কল করে। initialize()
ফাংশন থেকে একটি মিথ্যা রিটার্ন মান পরিচালনা করা আপনার আবেদনের উপর নির্ভর করে। আপনি ব্যবহারকারীকে একটি ত্রুটি বার্তা দেখাতে পারেন যা নির্দেশ করে যে বর্তমান ডিভাইসটি ব্লুটুথ অপারেশনকে সমর্থন করে না বা ব্লুটুথের কাজ করার জন্য প্রয়োজন এমন কোনো বৈশিষ্ট্য অক্ষম করে না। নিম্নলিখিত উদাহরণে, ব্যবহারকারীকে পূর্ববর্তী স্ক্রিনে ফেরত পাঠানোর জন্য ক্রিয়াকলাপে finish()
বলা হয়।
কোটলিন
class DeviceControlActivity : AppCompatActivity() { // Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> if (!bluetooth.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth") finish() } // perform device connection } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } } ... }
জাভা
class DeviceControlsActivity extends AppCompatActivity { private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { if (!bluetoothService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } // perform device connection } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } }; ... }
একটি ডিভাইসের সাথে সংযোগ করুন
একবার BluetoothLeService
ইনস্ট্যান্স আরম্ভ হয়ে গেলে, এটি BLE ডিভাইসের সাথে সংযোগ করতে পারে। কার্যকলাপের জন্য পরিষেবাতে ডিভাইসের ঠিকানা পাঠাতে হবে যাতে এটি সংযোগ শুরু করতে পারে। ডিভাইসটি অ্যাক্সেস করার জন্য পরিষেবাটি প্রথমে BluetoothAdapter
এ getRemoteDevice()
কল করবে। যদি অ্যাডাপ্টার সেই ঠিকানা সহ একটি ডিভাইস খুঁজে না পায়, getRemoteDevice()
একটি IllegalArgumentException
নিক্ষেপ করে।
কোটলিন
fun connect(address: String): Boolean { bluetoothAdapter?.let { adapter -> try { val device = adapter.getRemoteDevice(address) } catch (exception: IllegalArgumentException) { Log.w(TAG, "Device not found with provided address.") return false } // connect to the GATT server on the device } ?: run { Log.w(TAG, "BluetoothAdapter not initialized") return false } }
জাভা
public boolean connect(final String address) { if (bluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } try { final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); } catch (IllegalArgumentException exception) { Log.w(TAG, "Device not found with provided address."); return false; } // connect to the GATT server on the device }
DeviceControlActivity
এই connect()
ফাংশনটিকে কল করে একবার পরিষেবাটি আরম্ভ হয়ে গেলে। কার্যকলাপটি BLE ডিভাইসের ঠিকানায় পাস করতে হবে। নিম্নলিখিত উদাহরণে, ডিভাইসের ঠিকানাটি অতিরিক্ত উদ্দেশ্য হিসাবে কার্যকলাপে প্রেরণ করা হয়েছে।
কোটলিন
// Code to manage Service lifecycle. private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected( componentName: ComponentName, service: IBinder ) { bluetoothService = (service as LocalBinder).getService() bluetoothService?.let { bluetooth -> if (!bluetooth.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth") finish() } // perform device connection bluetooth.connect(deviceAddress) } } override fun onServiceDisconnected(componentName: ComponentName) { bluetoothService = null } }
জাভা
private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bluetoothService = ((LocalBinder) service).getService(); if (bluetoothService != null) { if (!bluetoothService.initialize()) { Log.e(TAG, "Unable to initialize Bluetooth"); finish(); } // perform device connection bluetoothService.connect(deviceAddress); } } @Override public void onServiceDisconnected(ComponentName name) { bluetoothService = null; } };
GATT কলব্যাক ঘোষণা করুন
একবার কার্যকলাপটি পরিষেবাকে বলে যে কোন ডিভাইসের সাথে সংযোগ করতে হবে এবং পরিষেবাটি ডিভাইসের সাথে সংযুক্ত হলে, পরিষেবাটিকে BLE ডিভাইসে GATT সার্ভারের সাথে সংযোগ করতে হবে। এই সংযোগের জন্য একটি BluetoothGattCallback
প্রয়োজন সংযোগের অবস্থা, পরিষেবা আবিষ্কার, চারিত্রিক পঠন এবং বৈশিষ্ট্যযুক্ত বিজ্ঞপ্তিগুলি সম্পর্কে বিজ্ঞপ্তিগুলি পেতে৷
এই বিষয় সংযোগ রাষ্ট্র বিজ্ঞপ্তি উপর ফোকাস. কীভাবে পরিষেবা আবিষ্কার করতে হয়, চারিত্রিক পঠন এবং চরিত্রগত বিজ্ঞপ্তির অনুরোধ করতে হয় তার জন্য BLE ডেটা স্থানান্তর দেখুন।
ডিভাইসের GATT সার্ভারের সাথে সংযোগ পরিবর্তন হলে onConnectionStateChange()
ফাংশনটি ট্রিগার হয়। নিম্নলিখিত উদাহরণে, কলব্যাকটি Service
শ্রেণিতে সংজ্ঞায়িত করা হয়েছে যাতে পরিষেবাটি এটির সাথে সংযুক্ত হওয়ার পরে এটি BluetoothDevice
সাথে ব্যবহার করা যেতে পারে।
কোটলিন
private val bluetoothGattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server } } }
জাভা
private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server } } };
GATT পরিষেবার সাথে সংযোগ করুন৷
একবার BluetoothGattCallback
ঘোষণা করা হলে, পরিষেবাটি ডিভাইসে GATT পরিষেবার সাথে সংযোগ করতে connect()
ফাংশন থেকে BluetoothDevice
অবজেক্ট ব্যবহার করতে পারে।
connectGatt()
ফাংশন ব্যবহার করা হয়। এর জন্য একটি Context
বস্তু, একটি autoConnect
বুলিয়ান পতাকা এবং BluetoothGattCallback
প্রয়োজন। এই উদাহরণে, অ্যাপটি সরাসরি BLE ডিভাইসের সাথে সংযুক্ত হচ্ছে, তাই autoConnect
জন্য false
পাস করা হয়েছে।
একটি BluetoothGatt
প্রপার্টিও যোগ করা হয়েছে। এটি পরিষেবাটিকে সংযোগ বন্ধ করার অনুমতি দেয় যখন এটি আর প্রয়োজন হয় না।
কোটলিন
class BluetoothLeService : Service() { ... private var bluetoothGatt: BluetoothGatt? = null ... fun connect(address: String): Boolean { bluetoothAdapter?.let { adapter -> try { val device = adapter.getRemoteDevice(address) // connect to the GATT server on the device bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback) return true } catch (exception: IllegalArgumentException) { Log.w(TAG, "Device not found with provided address. Unable to connect.") return false } } ?: run { Log.w(TAG, "BluetoothAdapter not initialized") return false } } }
জাভা
class BluetoothLeService extends Service { ... private BluetoothGatt bluetoothGatt; ... public boolean connect(final String address) { if (bluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } try { final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address); // connect to the GATT server on the device bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback); return true; } catch (IllegalArgumentException exception) { Log.w(TAG, "Device not found with provided address. Unable to connect."); return false; } } }
সম্প্রচার আপডেট
যখন সার্ভারটি GATT সার্ভার থেকে সংযোগ বা সংযোগ বিচ্ছিন্ন করে, তখন এটিকে নতুন রাষ্ট্রের কার্যকলাপকে অবহিত করতে হবে। এটি সম্পন্ন করার বিভিন্ন উপায় আছে। নিম্নলিখিত উদাহরণটি পরিষেবা থেকে কার্যকলাপে তথ্য পাঠাতে সম্প্রচার ব্যবহার করে।
পরিষেবাটি নতুন রাজ্য সম্প্রচার করার জন্য একটি ফাংশন ঘোষণা করে। এই ফাংশনটি একটি অ্যাকশন স্ট্রিং নেয় যা সিস্টেমে সম্প্রচার করার আগে একটি Intent
অবজেক্টে পাস করা হয়।
কোটলিন
private fun broadcastUpdate(action: String) { val intent = Intent(action) sendBroadcast(intent) }
জাভা
private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); }
ব্রডকাস্ট ফাংশনটি চালু হয়ে গেলে, এটি GATT সার্ভারের সাথে সংযোগের অবস্থা সম্পর্কে তথ্য পাঠাতে BluetoothGattCallback
এর মধ্যে ব্যবহার করা হয়। ধ্রুবক এবং পরিষেবার বর্তমান সংযোগের অবস্থা Intent
অ্যাকশনের প্রতিনিধিত্বকারী পরিষেবাতে ঘোষণা করা হয়।
কোটলিন
class BluetoothLeService : Service() { private var connectionState = STATE_DISCONNECTED private val bluetoothGattCallback: BluetoothGattCallback = object : BluetoothGattCallback() { override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server connectionState = STATE_CONNECTED broadcastUpdate(ACTION_GATT_CONNECTED) } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server connectionState = STATE_DISCONNECTED broadcastUpdate(ACTION_GATT_DISCONNECTED) } } } ... companion object { const val ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED" const val ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED" private const val STATE_DISCONNECTED = 0 private const val STATE_CONNECTED = 2 } }
জাভা
class BluetoothLeService extends Service { public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTED = 2; private int connectionState; ... private final BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { // successfully connected to the GATT Server connectionState = STATE_CONNECTED; broadcastUpdate(ACTION_GATT_CONNECTED); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // disconnected from the GATT Server connectionState = STATE_DISCONNECTED; broadcastUpdate(ACTION_GATT_DISCONNECTED); } } }; … }
কার্যকলাপের আপডেটের জন্য শুনুন
পরিষেবা একবার সংযোগ আপডেট সম্প্রচার করলে, কার্যকলাপের জন্য একটি BroadcastReceiver
প্রয়োগ করতে হবে। অ্যাক্টিভিটি সেট-আপ করার সময় এই রিসিভারটি রেজিস্টার করুন, এবং অ্যাক্টিভিটি যখন স্ক্রীন ছেড়ে যাচ্ছে তখন এটি রেজিস্টার করুন। পরিষেবা থেকে ইভেন্টগুলি শোনার মাধ্যমে, কার্যকলাপটি BLE ডিভাইসের সাথে বর্তমান সংযোগের অবস্থার উপর ভিত্তি করে ব্যবহারকারীর ইন্টারফেস আপডেট করতে সক্ষম হয়।
কোটলিন
class DeviceControlActivity : AppCompatActivity() { ... private val gattUpdateReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { when (intent.action) { BluetoothLeService.ACTION_GATT_CONNECTED -> { connected = true updateConnectionState(R.string.connected) } BluetoothLeService.ACTION_GATT_DISCONNECTED -> { connected = false updateConnectionState(R.string.disconnected) } } } } override fun onResume() { super.onResume() registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter()) if (bluetoothService != null) { val result = bluetoothService!!.connect(deviceAddress) Log.d(DeviceControlsActivity.TAG, "Connect request result=$result") } } override fun onPause() { super.onPause() unregisterReceiver(gattUpdateReceiver) } private fun makeGattUpdateIntentFilter(): IntentFilter? { return IntentFilter().apply { addAction(BluetoothLeService.ACTION_GATT_CONNECTED) addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED) } } }
জাভা
class DeviceControlsActivity extends AppCompatActivity { ... private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { connected = true; updateConnectionState(R.string.connected); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { connected = false; updateConnectionState(R.string.disconnected); } } }; @Override protected void onResume() { super.onResume(); registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter()); if (bluetoothService != null) { final boolean result = bluetoothService.connect(deviceAddress); Log.d(TAG, "Connect request result=" + result); } } @Override protected void onPause() { super.onPause(); unregisterReceiver(gattUpdateReceiver); } private static IntentFilter makeGattUpdateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); return intentFilter; } }
ট্রান্সফার BLE ডেটাতে , BroadcastReceiver
পরিষেবা আবিষ্কারের সাথে সাথে ডিভাইস থেকে বৈশিষ্ট্যযুক্ত ডেটাও যোগাযোগ করতে ব্যবহৃত হয়।
GATT সংযোগ বন্ধ করুন
ব্লুটুথ সংযোগগুলি নিয়ে কাজ করার সময় একটি গুরুত্বপূর্ণ পদক্ষেপ হল সংযোগটি বন্ধ করা যখন আপনি এটি দিয়ে শেষ করেন৷ এটি করতে, BluetoothGatt
অবজেক্টে close()
ফাংশনটি কল করুন। নিম্নলিখিত উদাহরণে, পরিষেবাটি BluetoothGatt
এর রেফারেন্স ধারণ করে। ক্রিয়াকলাপটি পরিষেবা থেকে বন্ধ হয়ে গেলে, ডিভাইসের ব্যাটারি নিষ্কাশন এড়াতে সংযোগটি বন্ধ থাকে৷
কোটলিন
class BluetoothLeService : Service() { ... override fun onUnbind(intent: Intent?): Boolean { close() return super.onUnbind(intent) } private fun close() { bluetoothGatt?.let { gatt -> gatt.close() bluetoothGatt = null } } }
জাভা
class BluetoothLeService extends Service { ... @Override public boolean onUnbind(Intent intent) { close(); return super.onUnbind(intent); } private void close() { if (bluetoothGatt == null) { Return; } bluetoothGatt.close(); bluetoothGatt = null; } }