I don't know if I understood correctly the question, but you need to create a new class file with the LeDeviceListAdapter class definition. Then you need to import it inside the file you are using it.
For some info about BLE you can check my question:
QUESTION
And my answer:
ANSWER
In my answer you can find a class (TagBLE and DataTagBLE) to manage the bluetooth device you find ^^ You can use it and implement a list of them to manage the results from your scan then use a RecyclerView with specific RecyclerView Adapter to show all the devices :D
If you need any help just ask me, I can provice you the code I'm using and explain it to you (: For example I can give you the services and activities I'm using to scan and retrieve BLE :D
Also check this answer:
Answer about LeDeviceListAdapter
I had the code for a service that do the background scan for the BLE and a Base Activity that manage getting the TAG INFO. You can use this for references or import it in your project. It will use a service to scan for the BLE and get the results in the activity
BaseTagsScanService.java:
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseTagsScanService extends Service {
private static final String TAG = BaseTagsScanService.class.getName();
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothLeScanner mBLEScanner;
private ScanCallback mScanCallback;
private boolean mIsScanning;
/** Abstract Methods **/
protected abstract ScanSettings getScanSettings();
protected abstract List<ScanFilter> getScanFilters();
protected abstract void manageScanResult(ScanResult result);
protected abstract void onScanFail(int errorCode);
/** Override Lifecycle Methods **/
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
initBluetooth();
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
initBluetooth();
return null;
}
@Override
public void onDestroy() {
unsetAll();
super.onDestroy();
}
/** Protected Methods **//** Init Methods **/
protected void initBluetooth(){
initBluetoothAdapter();
if(mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
initBluetoothLeScanner();
initBluetoothScanCallback();
}
}
/** Getter Methods **/
@Nullable
protected BluetoothAdapter getBluetoothAdapter(){
return mBluetoothAdapter;
}
@Nullable
protected BluetoothManager getBluetoothManager(){
return mBluetoothManager;
}
@Nullable
protected BluetoothLeScanner getBLEScanner(){
return mBLEScanner;
}
@Nullable
protected ScanCallback getScanCallback(){
return mScanCallback;
}
/** BLEScanner Methods **/
protected void unsetBLEScanner(){
if(mBLEScanner != null && mIsScanning && mBluetoothAdapter.isEnabled()){
mBLEScanner.stopScan(mScanCallback);
}
mBLEScanner = null;
}
/** Scan Methods **/
protected boolean isScanning(){
return mIsScanning;
}
protected void setIsScanning(boolean isScanning){
mIsScanning = isScanning;
}
protected boolean startScan(){
boolean ret = false;
if(checkStartScan()){
ret = true;
mIsScanning = true;
if(mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
mBLEScanner.startScan(getScanFilters(), getScanSettings(), mScanCallback);
}
}
return ret;
}
protected boolean stopScan(){
boolean ret = false;
if(checkStopScan()){
ret = true;
mIsScanning = false;
if(mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
mBLEScanner.stopScan(mScanCallback);
}
}
return ret;
}
/** ScanFilter Methods **/
protected List<ScanFilter> buildScanFilters(List<String> macs){
List<ScanFilter> scanFilters = new ArrayList<>();
if(macs != null && macs.size() > 0x0){
scanFilters = new ArrayList<>();
for(String mac : macs){
ScanFilter filter = new ScanFilter
.Builder()
.setDeviceAddress(mac)
.build();
scanFilters.add(filter);
}
} else {
scanFilters.add(new ScanFilter.Builder().build());
}
return scanFilters;
}
/** Private Methods **//** Init Methods **/
private void initBluetoothAdapter(){
mBluetoothManager = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
if(mBluetoothManager != null){
mBluetoothAdapter = mBluetoothManager.getAdapter();
}
}
private void initBluetoothLeScanner(){
mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
private void initBluetoothScanCallback(){
mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
manageScanResult(result);
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
@Override
public void onScanFailed(int errorCode) {
super.onScanFailed(errorCode);
onScanFail(errorCode);
Log.e("CheckInOut_Admin", "onScanFailed - errorCode = " + errorCode);
}
};
}
/** Unset Methods **/
private void unsetAll(){
unsetBLEScanner();
unsetBluetoothAdapter();
}
private void unsetBluetoothAdapter(){
mBluetoothAdapter = null;
mBluetoothManager = null;
}
/** Check Scan Methods **/
private boolean checkStartScan(){
return !mIsScanning && mBLEScanner != null;
}
private boolean checkStopScan(){
return mIsScanning && mBLEScanner != null;
}
}
TagsScanService.java:
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.emax.it.lib_base.BaseConstants;
import com.emax.it.lib_base.BaseEnvironment;
import com.emax.it.lib_base.modules.handlers.MessageHandler;
import com.emax.it.lib_base.modules.handlers.MessageManager;
import com.emax.it.lib_base.ui.receivers.BluetoothStatusChangedReceiver;
import com.emax.it.lib_base.ui.receivers.ProviderStatusChangedReceiver;
import com.emax.it.lib_ble.base_activities.BaseTagsScanActivity;
import com.emax.it.lib_ble.models.TagBle;
import com.emax.it.lib_ble.services.base.BaseTagsScanService;
import com.emax.it.lib_ble.utils.BluetoothUtils;
import java.util.ArrayList;
import java.util.List;
public class TagsScanService extends BaseTagsScanService
implements BluetoothStatusChangedReceiver.IOnBluetoothStatusChanged,
ProviderStatusChangedReceiver.IOnProviderStatusChanged,
MessageHandler.IOnHandleMessage {
private static final String TAG = TagsScanService.class.getSimpleName();
// Messages Whats
public static final int MSG_WHAT_SCAN_START = 0x5C1;
public static final int MSG_WHAT_SCAN_STOP = 0x5C2;
public static final int MSG_WHAT_BLUETOOTH_OFF = 0x5C3;
public static final int MSG_WHAT_GPS_OFF = 0x5C4;
public static final int MSG_WHAT_BLE_TAG = 0x5C5;
// Messages Args
public static final int MSG_ARG_ONE_FAIL = 0x0;
public static final int MSG_ARG_ONE_SUCCESS = 0x1;
private BluetoothStatusChangedReceiver mBluetoothReceiver;
private ProviderStatusChangedReceiver mProviderReceiver;
private MessageManager mMessenger;
/** Override BaseTagsScanService Methods **/
@Override
protected ScanSettings getScanSettings(){
return new ScanSettings
.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.build();
}
@Override
protected List<ScanFilter> getScanFilters(){
return new ArrayList<>();
}
@Override
protected void manageScanResult(ScanResult result) {
if(result != null){
BluetoothDevice device = result.getDevice();
if(!TextUtils.isEmpty(device.getAddress())){
sendTag(TagBle.initInstanceFromScanResult(result, BluetoothUtils.getBeaconTxPower(result)), result.getRssi());
}
}
}
@Override
protected void onScanFail(int errorCode) {
switch (errorCode){
case ScanCallback.SCAN_FAILED_ALREADY_STARTED:
if(getBLEScanner() != null){
getBLEScanner().stopScan(getScanCallback());
getBLEScanner().startScan(getScanFilters(), getScanSettings(), getScanCallback());
}
break;
case ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
if(getBluetoothAdapter() != null){
getBLEScanner().stopScan(getScanCallback());
getBluetoothAdapter().disable();
new Handler().postDelayed(() -> {
getBluetoothAdapter().enable();
new Handler().postDelayed(() -> getBLEScanner().startScan(getScanFilters(), getScanSettings(), getScanCallback()), BaseConstants.MILLIS_QUARTER_SECOND);
}, BaseConstants.MILLIS_QUARTER_SECOND);
}
break;
}
}
/** Override Lifecycle Methods **/
@Override
public void onCreate() {
super.onCreate();
initOnCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
super.onBind(intent);
initMessageManager();
return mMessenger.getMsgReceiver().getBinder();
}
@Override
public void onDestroy() {
unsetBluetoothStatusReceiver();
unsetProviderStatusReceiver();
super.onDestroy();
}
/** Override BluetoothStatusChangedReceiver.IOnBluetoothStatusChanged Methods **/
public void onBluetoothStatusChanged(int status){
if(status == BluetoothAdapter.STATE_TURNING_OFF){
stopScan();
sendBluetoothOff();
} else if(BluetoothUtils.checkBLE(this)){
initBluetooth();
}
}
/** Override ProviderStatusChangedReceiver.IOnProviderStatusChanged Methods **/
@Override
public void onProviderStatusChanged(int status) {
if(status == ProviderStatusChangedReceiver.IOnProviderStatusChanged.STATUS_DISABLED){
stopScan();
sendGpsOff();
} else if(BluetoothUtils.checkBLE(this)){
initBluetooth();
}
}
/** Override IOnHandleMessage Callback Methods **/
@Override
public void onHandleMessage(Message msg) {
switch(msg.what){
case MSG_WHAT_SCAN_START:
boolean started = startScan();
sendScanStarted(started ? MSG_ARG_ONE_SUCCESS : MSG_ARG_ONE_FAIL, msg.arg2);
break;
case MSG_WHAT_SCAN_STOP:
boolean stopped = stopScan();
sendScanStopped(stopped ? MSG_ARG_ONE_SUCCESS : MSG_ARG_ONE_FAIL, msg.arg2);
break;
}
}
/** Protected Methods **/
protected <T extends Parcelable> void sendTag(T tag, int rssi){
if(mMessenger != null){
Bundle data = new Bundle();
data.putParcelable(BaseTagsScanActivity.EXTRA_BLE_TAG, tag);
data.putInt(BaseTagsScanActivity.EXTRA_RSSI_VALUE, rssi);
mMessenger.sendMessage(MSG_WHAT_BLE_TAG, 0x0, 0x0, data);
}
}
protected MessageManager getMessenger(){
return mMessenger;
}
/** Private Methods **//** Init Methods **/
private void initOnCreate(){
initRegisterBluetoothStatusChangedReceiver();
initRegisterProviderStatusChangedReceiver();
}
private void initMessageManager(){
mMessenger = new MessageManager(this);
}
private void initRegisterBluetoothStatusChangedReceiver(){
initBluetoothAdapterReceiver();
registerBluetoothAdapterReceiver();
}
private void initRegisterProviderStatusChangedReceiver(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
initProviderStatusChangedReceiver();
registerProviderStatusChangedReceiver();
} else {
mProviderReceiver = null;
}
}
private void initBluetoothAdapterReceiver(){
mBluetoothReceiver = new BluetoothStatusChangedReceiver(this);
}
private void initProviderStatusChangedReceiver(){
mProviderReceiver = new ProviderStatusChangedReceiver(this);
}
/** Register Receivers Methods **/
private void registerBluetoothAdapterReceiver(){
if(mBluetoothReceiver != null && !mBluetoothReceiver.isRegistered()) {
registerReceiver(mBluetoothReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
mBluetoothReceiver.setIsRegistered(true);
}
}
private void registerProviderStatusChangedReceiver(){
if(mProviderReceiver != null && !mProviderReceiver.isRegistered()){
registerReceiver(mProviderReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION));
mProviderReceiver.setIsRegistered(true);
}
}
/** Unset Methods **/
private void unsetBluetoothStatusReceiver(){
if(mBluetoothReceiver != null) {
try {
unregisterReceiver(mBluetoothReceiver);
} catch (RuntimeException rE) {
BaseEnvironment.onExceptionLevelLow(TAG, rE);
}
mBluetoothReceiver = null;
}
}
private void unsetProviderStatusReceiver(){
if(mProviderReceiver != null){
try {
unregisterReceiver(mProviderReceiver);
} catch (RuntimeException rE){
BaseEnvironment.onExceptionLevelLow(TAG, rE);
}
mProviderReceiver = null;
}
}
/** Messenger Methods **/
private void sendScanStarted(int arg1, int arg2){
if(mMessenger != null ){
mMessenger.sendMessage(MSG_WHAT_SCAN_START, arg1, arg2, null);
}
}
private void sendScanStopped(int arg1, int arg2){
if(mMessenger != null){
mMessenger.sendMessage(MSG_WHAT_SCAN_STOP, arg1, arg2,null);
}
}
private void sendBluetoothOff(){
if(mMessenger != null){
mMessenger.sendMessage(MSG_WHAT_BLUETOOTH_OFF, 0x0, 0x0, null);
}
}
private void sendGpsOff(){
if(mMessenger != null){
mMessenger.sendMessage(MSG_WHAT_GPS_OFF, 0x0, 0x0, null);
}
}
}
BaseTagsScanActivity.java:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcelable;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.emax.it.lib_base.modules.handlers.MessageHandler;
import com.emax.it.lib_base.modules.handlers.MessageManager;
import com.emax.it.lib_base.ui.activities.BaseAppCompatActivity;
import com.emax.it.lib_ble.LibBleConstants;
import com.emax.it.lib_ble.R;
import com.emax.it.lib_ble.models.TagBle;
import com.emax.it.lib_ble.services.TagsScanService;
import com.emax.it.lib_ble.utils.BluetoothUtils;
public abstract class BaseTagsScanActivity extends BaseAppCompatActivity
implements MessageHandler.IOnHandleMessage,
BluetoothUtils.ICheckStatusBLE {
private static final String TAG = BaseTagsScanActivity.class.getSimpleName();
private static final String EXTRA = TAG + ".extra";
// Intents Extras
public static final String EXTRA_BLE_TAG = EXTRA + ".tagBLE";
public static final String EXTRA_RSSI_VALUE = EXTRA + ".valueRSSI";
protected Handler mScanHandler;
protected MessageManager mMessenger;
protected BLEScanServiceConnection mServiceConnection;
protected boolean mBound;
/** Override Lifecycle Methods **/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initOnCreate();
}
@Override
protected void onStart() {
super.onStart();
BluetoothUtils.doFullCheckEnableBLE(this, this);
}
@Override
protected void onStop() {
super.onStop();
unbindToService();
}
@Override
protected void onDestroy() {
if(mScanHandler != null){
mScanHandler.removeCallbacksAndMessages(null);
mScanHandler = null;
}
mMessenger = null;
unbindToService();
stopTagsScanService();
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == LibBleConstants.REQ_PERMISSION_BLUETOOTH_LOCATION) {
if (grantResults.length > 0x0 && grantResults[0x0] == PackageManager.PERMISSION_GRANTED) {
BluetoothUtils.doFullCheckEnableBLE(this, this);
} else {
Toast.makeText(this, getString(R.string.error_permission_not_granted), Toast.LENGTH_SHORT).show();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case LibBleConstants.REQ_CODE_ENABLE_BT:
if(resultCode == RESULT_OK){
BluetoothUtils.doFullCheckEnableBLE(this, this);
} else {
finish();
}
break;
case LibBleConstants.REQ_CODE_BLE_ENABLE_GPS:
LocationManager lM = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (lM != null && lM.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
onSuccessCheckBLE();
} else {
Toast.makeText(this, getString(R.string.error_scan_tags_require_gps), Toast.LENGTH_LONG).show();
finish();
}
break;
}
}
/** Override Actionbar Listener Methods **/
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
}
return super.onOptionsItemSelected(item);
}
/** Override ICheckStatusBLE Methods **/
@Override
public void onCheckStatusBleOk(){
onSuccessCheckBLE();
}
@Override
public void onCheckStatusBleError(int err) {
finish();
}
/** Protected Methods **/
protected void callBaseOnCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
protected void callBaseOnStart(){
super.onStart();
}
protected void initOnCreate(){
if(getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
mBound = false;
initMyServiceConnection();
initScanHandler();
}
protected void initScanHandler(){
mScanHandler = new Handler();
}
/** Service Methods **/
protected void stopTagsScanService(){
stopService(new Intent(this, TagsScanService.class));
}
protected void bindToTagsScanService(){
bindService(new Intent(this, TagsScanService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
}
protected void unbindToService(){
if(mBound) {
unbindService(mServiceConnection);
mBound = false;
}
}
/** Scan Methods **/
protected void startScan(int arg1, int arg2, @Nullable Bundle data){
startScan(TagsScanService.MSG_WHAT_SCAN_START, arg1, arg2, data);
}
protected void startScan(int what, int arg1, int arg2, @Nullable Bundle data){
if(mMessenger != null){
mMessenger.sendMessage(what, arg1, arg2, data);
}
}
protected void stopScan(int arg1, int arg2, @Nullable Bundle data){
if(mMessenger != null){
mMessenger.sendMessage(TagsScanService.MSG_WHAT_SCAN_STOP, arg1, arg2, data);
}
}
protected void startScanHandler(Runnable runnable, long time){
if(mScanHandler == null){
initScanHandler();
}
mScanHandler.postDelayed(runnable, time);
}
/** Check Methods **/
protected boolean checkStartStopScan(){
boolean ret = false;
boolean checkBLE = BluetoothUtils.checkBLE(this);
if(mBound && checkBLE){
ret = true;
} else if(!mBound && checkBLE){
showMessageServiceError();
} else {
BluetoothUtils.doFullCheckEnableBLE(this, this);
}
return ret;
}
/** Handle Message Methods **/
protected void onHandleMessageBluetoothOff(){
BluetoothUtils.doFullCheckEnableBLE(this, this);
}
protected void onHandleMessageGpsOff(){
BluetoothUtils.doFullCheckEnableBLE(this, this);
}
protected <T extends Parcelable> T getTagBleFromBundle(Bundle data){
if(data != null && data.containsKey(EXTRA_BLE_TAG)){
return (T) data.getParcelable(EXTRA_BLE_TAG);
}
return null;
}
protected int getRssiFromBundle(Bundle data){
if(data != null && data.containsKey(BaseTagsScanActivity.EXTRA_RSSI_VALUE)){
return data.getInt(BaseTagsScanActivity.EXTRA_RSSI_VALUE, 0x0);
}
return 0x0;
}
/** Messages Methods **/
protected void showMessageServiceError(){
Toast.makeText(this, R.string.error_scan_service_not_started, Toast.LENGTH_SHORT).show();
}
protected void showMessageScanStartError(){
Toast.makeText(this, R.string.error_start_scan, Toast.LENGTH_LONG).show();
}
protected void showMessageScanStopError(){
Toast.makeText(this, R.string.error_stop_scan, Toast.LENGTH_SHORT).show();
}
/** Private Methods **//** Init Methods **/
private void initMyServiceConnection(){
mServiceConnection = new BLEScanServiceConnection();
}
private void initMyMessenger(IBinder iBinder){
mMessenger = new MessageManager(this, iBinder);
mMessenger.sendHandshake();
}
/** Service Methods **/
private void onSuccessCheckBLE(){
bindToTagsScanService();
}
/** Private Classes **/
protected class BLEScanServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
initMyMessenger(iBinder);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mMessenger = null;
mBound = false;
}
}
}
Rest of code you have the classes in my answer above and the message handlers in this answer:
Message Handlers between service and activity