You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
9.6 KiB
Java

package com.waveshare.epaperesp32loader.communication;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.support.annotation.NonNull;
import com.waveshare.epaperesp32loader.ScanningActivity;
/**
* Created by YiWan on 8/19/2018.
*/
/**
* <h1>Bluetooth scanner</h1>
* The class provides functions for receiving bluetooth broadcast messages
* (bluetooth is on\off, discovering is on\off, new device found),
* requesting ACCESS_COARSE_LOCATION permission and devices scanning.
*
* @author Waveshare team
* @version 1.0
* @since 8/19/2018
*/
public class BluetoothScanner
{
// Bluetooth scanning objects
//-----------------------------
private static BluetoothAdapter btAdapter;
private static BluetoothBroadcastReceiver btReceiver;
private static ScanningHandler btHandler;
// Keys of scanning events
//-----------------------------
public static final int BT_SCANNING_ON = 2;
public static final int BT_SCANNING_OFF = 3;
public static final int BT_IS_CHANGED = 4;
public static final int BT_DEVICE_FOUND = 5;
//--------------------------------------
// Permission
//--------------------------------------
private static PermissionHelper permissionHelper;
private static PermissionHelper.PermissionResponse permissionResponse;
//---------------------------------------------------------
// Scanning message handler
//---------------------------------------------------------
public interface ScanningHandler
{
void handleMessage(int cmnd, Intent data);
}
//---------------------------------------------------------
// Broadcast receiver of bluetooth adapter events:
//
// ACTION_STATE_CHANGED - bluetooth on/off
// ACTION_DISCOVERY_STARTED - scanning on
// ACTION_DISCOVERY_FINISHED - scanning off
// ACTION_FOUND - some device is found
//---------------------------------------------------------
private static class BluetoothBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(BluetoothDevice.ACTION_FOUND))
btHandler.handleMessage(BT_DEVICE_FOUND, intent);
else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))
btHandler.handleMessage(BT_IS_CHANGED, intent);
else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED))
btHandler.handleMessage(BT_SCANNING_ON, null);
else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED))
btHandler.handleMessage(BT_SCANNING_OFF, null);
}
}
//---------------------------------------------------------
// Tries to start scanning process
// Returns true if the starting is successful
// Returns false if the starting needs permission
//---------------------------------------------------------
public static boolean initialize(Activity activity)
{
// Permission required for scanning
//-----------------------------------------------------
permissionHelper = new PermissionHelper(activity);
//-----------------------------------------------------
// Start the scanning if it is granted
//
// This class exemplar is analog of C#'s delegate.
// It wraps invoke function and is stored in the
// permissionHelper, just because function invoke
// can't be stored as a variable in Java.
//-----------------------------------------------------
permissionResponse = new PermissionHelper.PermissionResponse()
{
// It must be executed if the permission is granted
//-------------------------------------------------
@Override
public void invoke()
{
// Start the scanning of bluetooth devices
//---------------------------------------------
btAdapter.startDiscovery();
}
};
// Permission of ACCESS_COARSE_LOCATION
//--------------------------------------
permissionHelper.setResponse(PermissionHelper.REQ_BLUE, permissionResponse);
// Get available bluetooth adapter
//-----------------------------------------------------
btAdapter = BluetoothAdapter.getDefaultAdapter();
// Exit, if the adapter is not available
//-----------------------------------------------------
if (btAdapter == null) return false;
// Message handler
//-----------------------------------------------------
btHandler = (ScanningHandler)activity;
// Broadcast receiver of bluetooth events
//-----------------------------------------------------
btReceiver = new BluetoothBroadcastReceiver();
//-----------------------------------------------------
// Intent filter for bluetooth events:
//
// ACTION_STATE_CHANGED - bluetooth on/off
// ACTION_DISCOVERY_STARTED - scanning on
// ACTION_DISCOVERY_FINISHED - scanning off
// ACTION_FOUND - some device is found
//-----------------------------------------------------
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
activity.registerReceiver(btReceiver, intentFilter);
//-----------------------------------------------------
// Turn bluetooth on if it isn't on yet
//
// In fact, if btAdapter is off then following
// command sends request ACTION_REQUEST_ENABLE
// to turn on btAdapter and the broadcast receiver
// gets STATE_TURNING_ON message, which means
// the adapter started the turning on process.
// The scanning routine is interesting in STATE_ON
// and STATE_OFF messages only and ignores others.
//-----------------------------------------------------
if (!btAdapter.isEnabled()) activity.startActivity(
new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE));
return true;
}
//---------------------------------------------------------
// Checks if the device is scanning now
//---------------------------------------------------------
public static boolean isScanning()
{
return (btAdapter != null) && btAdapter.isDiscovering();
}
//---------------------------------------------------------
// Tries to start scanning process
// Returns true if the starting is successful
// Returns false if the scanning needs permission
//---------------------------------------------------------
public static boolean startScanning()
{
if (btAdapter.isDiscovering())
return true;
else if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ||
permissionHelper.sendRequestPermission(PermissionHelper.REQ_BLUE))
permissionResponse.invoke();
return false;
}
//---------------------------------------------------------
// Stops scanning process and unregisters receiver
//---------------------------------------------------------
public static void stopScanning(Activity activity, boolean unregisterReceiver)
{
try
{
// Stop getting messages from broadcast receiver
//-------------------------------------------------
if (unregisterReceiver)
activity.unregisterReceiver(btReceiver);
// Stop scanning bluetooth devices
//-------------------------------------------------
if ((btAdapter != null) && btAdapter.isDiscovering())
btAdapter.cancelDiscovery();
}
catch (Exception e)
{
}
}
//---------------------------------------------------------
// Sends request of scanning permission
//---------------------------------------------------------
public static void sendRequestPermission()
{
if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ||
permissionHelper.sendRequestPermission(PermissionHelper.REQ_BLUE))
permissionResponse.invoke();
}
//---------------------------------------------------------
// Request's result of the scanning permission
//---------------------------------------------------------
public static void onRequestPermissionsResult(
// Expected arguments:
int requestCode, // PermissionHelper.REQ_BLUE
@NonNull String[] permissions, // Manifest.permission.ACCESS_COARSE_LOCATION
@NonNull int[] grantResults) // PackageManager.PERMISSION_GRANTED
{
permissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}