An insecure snail/classic-bluetooth

Android Traditional (Classic) Bluetooth Framework

Latest version

function

  • Support multi-device simultaneous connection
  • Supports observer monitoring or callback.Note: Observer monitoring and callback can only be one of them!
  • Support for controlling callback threads with comment@RunOn
  • Supports method default execution threads for setting callbacks or observers

To configure

  1. Because some of the features of jdk8 are used, the following configuration needs to be added to module's build.gradle:
//Pure java projects
android {
	compileOptions {
		sourceCompatibility JavaVersion.VERSION_1_8
		targetCompatibility JavaVersion.VERSION_1_8
	}
}

//Projects with kotlin need to be added to the project build.gradle
allprojects {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8

        kotlinOptions {
            jvmTarget = '1.8'
            apiVersion = '1.3'
            languageVersion = '1.3'
        }
    }
}
  1. Add dependencies in module's build.gradle, modified to the latest version, are usually available after synchronization:
dependencies {
	...
	implementation 'cn.wandersnail:classic-bluetooth:latestVersion'
	//Extra dependency
	implementation 'cn.wandersnail:common-full:latestVersion'
}
  1. If the download from jcenter fails.Add content to repositories in project build.gradle, preferably both, and synchronize again.
allprojects {
	repositories {
		...
		mavenCentral()
		maven { url 'https://dl.bintray.com/wandersnail/androidx/' }
	}
}

Usage method

Initialize SDK

There are two ways to instantiate:

  1. Automatically build instances by default, simply get them
//Instantiate and initialize
BTManager.getInstance().initialize(application);
  1. To build a custom instance, you must precede BTManager.getInstance()!!
BTManager manager = BTManager.getBuilder()
        .setExecutorService(executorService)//Custom thread pools are used to perform background tasks, or the default can be used
		.setObserveAnnotationRequired(false)//The {@link Observe} comment is not mandatory to receive a message from the observer, and performance will be better if it is mandatory
		.setMethodDefaultThreadMode(ThreadMode.MAIN)//Specify default threads for callback and observer methods
		.build();
manager.initialize(application);

Destroy SDK

//If you need to modify the configuration to re-instantiate midway, you can rebuild the BTManager instance after calling this method
BTManager.getInstance().destroy();

Log Output Control

BTManager.isDebugMode = true;;//Turn on log printing

Search Device

  1. Define search listeners

    Searches above Android 6.0 require at least fuzzy positioning privileges, and precise positioning privileges if targetSdkVersion is set above 29.Permissions require dynamic application

private DiscoveryListener discoveryListener = new DiscoveryListener() {
	@Override
	public void onDiscoveryStart() {
		//Search Start
	}

	@Override
	public void onDiscoveryStop() {
		//Search Stop
	}

    /**
     * Search for Bluetooth devices
     *
     * @param device Searched Devices
     */
	@Override
	public void onDeviceFound(@NonNull BluetoothDevice device) {
		//search result
	}

	@Override
	public void onDiscoveryError(int errorCode, @NotNull String errorMsg) {
		switch(errorCode) {
			case ScanListener.ERROR_LACK_LOCATION_PERMISSION://Missing Location Permission		
				break;
			case ScanListener.ERROR_LOCATION_SERVICE_CLOSED://Location service not turned on		
				break;
			case ScanListener.ERROR_SCAN_FAILED://search failed
				break;
		}
	}
};
  1. Add monitoring
BTManager.getInstance().addDiscoveryListener(discoveryListener);
  1. Start Search
BTManager.getInstance().startDiscovery();
  1. stop searching
BTManager.getInstance().stopDiscovery();
  1. Stop listening
BTManager.getInstance().removeDiscoveryListener(discoveryListener);

Observer Mode Data and Events

  1. Define the observer.Implement the EventObserver interface:
public class MainActivity extends AppCompatActivity implements EventObserver {
    /**
     * Use {@link Observe} to determine if you want to receive a message, {@link RunOn} to specify a method to execute on the main thread, and {@link Tag} to prevent confusion.
     */
    @Tag("onConnectionStateChanged") 
    @Observe
    @RunOn(ThreadMode.MAIN)
    @Override
    public void onConnectionStateChanged(@NonNull BluetoothDevice device, int state) {
        switch (state) {
            case Connection.STATE_CONNECTING:
                break;
            case Connection.STATE_PAIRING:
                break;
            case Connection.STATE_PAIRED:
                break;
            case Connection.STATE_CONNECTED:
                break;
            case Connection.STATE_DISCONNECTED:
                break;            
            case Connection.STATE_RELEASED:
                break;
        }
    }
	
    /**
     * If {@link BTManager.Builder#setObserveAnnotationRequired(boolean)} is set to false, a message will be received regardless of the {@link Observe} comment.
     * When set to true, you must add {@link Observe} to receive the message.
     * The default is false, and the method default execution thread is specified in {@link BTManager.Builder#setMethodDefaultThreadMode(ThreadMode)}
     */
    @Observe
    @Override
    public void onRead(@NonNull BluetoothDevice device, @NonNull byte[] value) {
        Log.d("BTManager", "Data received:" + StringUtils.toHex(value, " "));
    }
    
    @Override
    public void onWrite(@NonNull BluetoothDevice device, @NonNull String tag, @NonNull byte[] value, boolean result) {
        Log.d("BTManager", "Write results:" + result);
    }
}
  1. Register Observers
BTManager.getInstance().registerObserver(observer);
  1. Unregister Observers
BTManager.getInstance().unregisterObserver(observer);

Connect

  1. Set up a connection
connection = BTManager.getInstance().createConnection(device, observer);//Observer listens for connection status
//If null is passed, connect using {@link #SPP_UUID} by default
connection.connect(uuid, new ConnectCallback() {
    @Override
    public void onSuccess() {
      
    }
    
    @Override
    public void onFail(@NonNull String errMsg, @Nullable Throwable e) {
    
    }
});
  1. Disconnect and reconnect
BTManager.getInstance().disconnectConnection(device);//Disconnect the specified connection
//BTManager.getInstance().disconnectAllConnections();//Disconnect all connections
  1. Release connection, no reconnection, connection needs to be re-established
BTManager.getInstance().releaseConnection(device);//Release the specified connection
//BTManager.getInstance().releaseAllConnections();//Release all connections

Read and write data

  1. receive data

The definition observer mentioned above.Implement the EventObserver interface to receive data in onRead.

  1. Write data

Two ways:

2.1 Interface Callback

/**
 * Write data, join the end of the queue
 *
 * @param tag      Data Identification
 * @param value    Data to be written
 * @param callback Write callback.When not null, the result is written back as a callback; when null is passed, the result is written back as a notification to the observer
 */
connection.write(tag, value, new WriteCallback() {
    @Override
    public void onWrite(@NonNull BluetoothDevice device, @NonNull String tag, @NonNull byte[] value, boolean result) {
        
    }
});

/**
 * Write data, join the queue at the top
 *
 * @param tag      Data Identification
 * @param value    Data to be written
 * @param callback Write callback.When not null, the result is written back as a callback; when null is passed, the result is written back as a notification to the observer
 */
connection.writeImmediately(tag, value, new WriteCallback() {
    @Override
    public void onWrite(@NonNull BluetoothDevice device, @NonNull String tag, @NonNull byte[] value, boolean result) {
     
    }
});

2.2 Receive results in observer mode

As with receiving data, the observer is defined.Implement the EventObserver interface to receive write results in onWrite.

Release the SDK and it must be reinitialized before it can be used

BTManager.getInstance().release();

Code confusion

-keep class * implements cn.wandersnail.commons.observer.Observe {
	public <methods>;
}

Demo Effect Preview

Tags: Gradle Android SDK Java

Posted on Sat, 09 May 2020 21:22:46 -0700 by mjs87