28import java.security.PrivilegedAction;
29import java.util.ArrayList;
30import java.util.Iterator;
32import java.util.concurrent.CopyOnWriteArrayList;
33import java.util.function.Consumer;
34import java.util.function.Predicate;
36import org.direct_bt.BTAdapter;
37import org.direct_bt.BTException;
38import org.direct_bt.BTFactory;
39import org.direct_bt.BTManager;
46 private static volatile boolean isJVMShuttingDown =
false;
47 private static final List<Runnable> userShutdownHooks =
new ArrayList<Runnable>();
53 Runtime.getRuntime().addShutdownHook(
54 new Thread(
null,
new Runnable() {
58 } },
"DBTManager_ShutdownHook" ) ) ;
60 System.err.println(
"DBTManager.init(): JVM ShutdownHook installed, on thread "+Thread.currentThread().getName());
66 private static synchronized void shutdownImpl(
final boolean _isJVMShuttingDown) {
67 isJVMShuttingDown = _isJVMShuttingDown;
69 System.err.println(
"DBTManager.shutdown() START: JVM ShutdownHook "+isJVMShuttingDown+
", on thread "+Thread.currentThread().getName());
71 synchronized(userShutdownHooks) {
72 final int cshCount = userShutdownHooks.size();
73 for(
int i=0; i < cshCount; i++) {
76 System.err.println(
"DBTManager.shutdown - userShutdownHook #"+(i+1)+
"/"+cshCount);
78 userShutdownHooks.get(i).run();
79 }
catch(
final Throwable t) {
80 System.err.println(
"DBTManager.shutdown: Caught "+t.getClass().getName()+
" during userShutdownHook #"+(i+1)+
"/"+cshCount);
86 userShutdownHooks.clear();
89 System.err.println(
"DBTManager.shutdown(): Post userShutdownHook");
95 }
catch(
final Throwable t) {
96 System.err.println(
"DBTManager.shutdown: Caught "+t.getClass().getName()+
" during DBTManager.shutdown()");
103 System.err.println(Thread.currentThread().getName()+
" - DBTManager.shutdown() END JVM Shutdown "+isJVMShuttingDown);
116 public static final void addShutdownHook(
final boolean head,
final Runnable runnable) {
117 synchronized( userShutdownHooks ) {
118 if( !userShutdownHooks.contains( runnable ) ) {
120 userShutdownHooks.add(0, runnable);
122 userShutdownHooks.add( runnable );
128 private long nativeInstance;
129 private final List<BTAdapter> adapters =
new CopyOnWriteArrayList<BTAdapter>();
130 private final List<ChangedAdapterSetListener> changedAdapterSetListenerList =
new CopyOnWriteArrayList<ChangedAdapterSetListener>();
133 public final List<BTAdapter>
getAdapters() {
return new ArrayList<BTAdapter>(adapters); }
137 for(
final Iterator<BTAdapter> iter = adapters.iterator(); iter.hasNext(); ) {
153 for(
final Iterator<BTAdapter> iter = adapters.iterator(); iter.hasNext(); ) {
164 changedAdapterSetListenerList.add(l);
166 adapters.forEach(
new Consumer<BTAdapter>() {
168 public void accept(
final BTAdapter adapter) {
177 final int count[] = { 0 };
178 changedAdapterSetListenerList.removeIf(
new Predicate<ChangedAdapterSetListener>() {
193 final int count = changedAdapterSetListenerList.size();
194 changedAdapterSetListenerList.clear();
198 private native List<BTAdapter> getAdapterListImpl();
199 private native
BTAdapter getAdapterImpl(
int dev_id);
206 final boolean removeAdapter(
final DBTAdapter adapter) {
207 if( adapters.remove(adapter) ) {
209 System.err.println(
"DBTManager.removeAdapter: Removed "+adapter);
214 System.err.println(
"DBTManager.removeAdapter: Not found "+adapter);
221 final void removeAdapterCB(
final int dev_id,
final int opc_reason) {
222 final BTAdapter[] removed = {
null };
223 final int count[] = { 0 };
224 adapters.removeIf(
new Predicate<BTAdapter>() {
226 public boolean test(
final BTAdapter a) {
227 if( 0 == count[0] && dev_id == a.getDevID() ) {
236 if(
null != removed[0] ) {
238 System.err.println(
"DBTManager.removeAdapterCB[dev_id "+dev_id+
", opc 0x"+Integer.toHexString(opc_reason)+
239 "]: removing "+removed[0].toString());
241 if( 0x0005 == opc_reason ) {
243 changedAdapterSetListenerList.forEach(
new Consumer<ChangedAdapterSetListener>() {
245 public void accept(
final ChangedAdapterSetListener t) {
246 t.adapterRemoved( removed[0] );
252 System.err.println(
"DBTManager.removeAdapterCB[dev_id "+dev_id+
", opc 0x"+Integer.toHexString(opc_reason)+
253 "]: removed "+count[0]+
" adapter, size "+adapters.size());
257 private final void updatedAdapterCB(
final int dev_id,
final int opc_reason) {
258 final BTAdapter preInstance =
getAdapter(dev_id);
259 if(
null != preInstance ) {
261 System.err.println(
"DBTManager.updatedAdapterCB[dev_id "+dev_id+
", opc 0x"+Integer.toHexString(opc_reason)+
262 "]: existing "+preInstance.toString()+
", size "+adapters.size());
266 final BTAdapter newInstance = getAdapterImpl(dev_id);
267 if(
null == newInstance ) {
269 System.err.println(
"DBTManager.updatedAdapterCB[dev_id "+dev_id+
", opc 0x"+Integer.toHexString(opc_reason)+
270 "]: Adapter not found, size "+adapters.size());
274 final boolean added = adapters.add(newInstance);
276 System.err.println(
"DBTManager.updatedAdapterCB[dev_id "+dev_id+
", opc 0x"+Integer.toHexString(opc_reason)+
277 "]: added "+added+
": new "+newInstance.toString()+
", size "+adapters.size());
279 if( added && 0x0004 == opc_reason ) {
281 changedAdapterSetListenerList.forEach(
new Consumer<ChangedAdapterSetListener>() {
283 public void accept(
final ChangedAdapterSetListener t) {
284 t.adapterAdded(newInstance);
289 private native
long ctorImpl() throws BTException;
290 private native
void dtorImpl(
long nativeInstance);
293 nativeInstance = ctorImpl();
295 adapters.addAll(getAdapterListImpl());
296 }
catch (
final BTException be) {
297 be.printStackTrace();
305 return LazySingletonHolder.singleton;
308 private static class LazySingletonHolder {
319 for(
final Iterator<BTAdapter> ia= adapters.iterator(); ia.hasNext(); ) {
326 synchronized( this ) {
327 handle = nativeInstance;
final void close()
Release the native memory associated with this object The object should not be used following a call ...
final List< BTAdapter > getAdapters()
Returns a list of BluetoothAdapters available in the system.
final void shutdown()
Release the native memory associated with this object and all related Bluetooth resources.
static final boolean DEBUG
int removeAllChangedAdapterSetListener()
Remove all added ChangedAdapterSetListener entries from this manager.
final int removeChangedAdapterSetListener(final ChangedAdapterSetListener l)
Remove the given ChangedAdapterSetListener from this manager.
final BTAdapter getAdapter(final int dev_id)
Returns the BluetoothAdapter matching the given dev_id or null if not found.
static final boolean VERBOSE
static final boolean isJVMShuttingDown()
Returns true if the JVM is shutting down, otherwise false.
static final BTManager getManager()
Returns an instance of BluetoothManager, to be used instead of constructor.
final void addChangedAdapterSetListener(final ChangedAdapterSetListener l)
Add the given ChangedAdapterSetListener to this manager.
final boolean setDefaultAdapter(final BTAdapter adapter)
Sets a default adapter to use for discovery.
final BTAdapter getDefaultAdapter()
Gets the default adapter to use for discovery.
static final void addShutdownHook(final boolean head, final Runnable runnable)
Add a shutdown hook to be performed at JVM shutdown before shutting down DBTManager instance.
One stop BTManager API entry point.
static final boolean VERBOSE
Verbose logging enabled or disabled.
static final boolean DEBUG
Debug logging enabled or disabled.
static< T > T doPrivileged(final PrivilegedAction< T > o)
Deprecated call to java.security.AccessController#doPrivileged(PrivilegedAction) w/o warnings.
BTAdapter represents one local Bluetooth Controller.
int getDevID()
Returns the BluetoothAdapter's internal temporary device id.
boolean isPowered()
Returns whether the adapter is valid, plugged in and powered.
Event listener to receive change events regarding the system's BTAdapter set, e.g.
void adapterAdded(final BTAdapter adapter)
BTAdapter was added to the system.
A thread safe singleton handler of the BTAdapter manager, e.g.