Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
BTFactory.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25package org.direct_bt;
26
27import java.io.IOException;
28import java.io.InputStream;
29import java.lang.reflect.InvocationTargetException;
30import java.lang.reflect.Method;
31import java.net.URL;
32import java.security.PrivilegedAction;
33import java.util.ArrayList;
34import java.util.Enumeration;
35import java.util.Iterator;
36import java.util.List;
37import java.util.Properties;
38import java.util.Set;
39import java.util.concurrent.atomic.AtomicReference;
40import java.util.jar.Attributes;
41import java.util.jar.Manifest;
42
43import org.jau.util.VersionUtil;
44
45/**
46 * One stop {@link BTManager} API entry point.
47 * <p>
48 * Further provides access to certain property settings,
49 * see {@link #DEBUG}, {@link #VERBOSE}, {@link #DEFAULT_BTMODE} and {@link BTManager.Settings}.
50 * </p>
51 */
52public class BTFactory {
53
54 /**
55 * Identifier names, allowing {@link BTFactory#getBTManager(ImplementationIdentifier)}
56 * to initialize the required native libraries and to instantiate the root {@link BTManager} instance.
57 * <p>
58 * The implementation class must provide the static factory method
59 * <pre>
60 * public static synchronized BluetoothManager getBluetoothManager() throws BluetoothException { .. }
61 * </pre>
62 * </p>
63 */
64 public static class ImplementationIdentifier {
65 /**
66 * Fully qualified class name for the {@link BTManager} implementation
67 * <p>
68 * The implementation class must provide the static factory method
69 * <pre>
70 * public static synchronized BluetoothManager getBluetoothManager() throws BluetoothException { .. }
71 * </pre>
72 * </p>
73 */
74 public final String BluetoothManagerClassName;
75 /** Native library basename for the implementation native library */
77 /** Native library basename for the Java binding native library */
78 public final String JavaNativeLibraryBasename;
79
82 final String JavaNativeLibraryBasename) {
83 this.BluetoothManagerClassName = BluetoothManagerClassName;
84 this.ImplementationNativeLibraryBasename = ImplementationNativeLibraryBasename;
85 this.JavaNativeLibraryBasename = JavaNativeLibraryBasename;
86 }
87
88 /**
89 * <p>
90 * Implementation compares {@link #BluetoothManagerClassName} only for equality.
91 * </p>
92 * {@inheritDoc}
93 */
94 @Override
95 public boolean equals(final Object other) {
96 if( null == other || !(other instanceof ImplementationIdentifier) ) {
97 return false;
98 }
101 }
102
103 @Override
104 public String toString() {
105 return "ImplementationIdentifier[class "+BluetoothManagerClassName+
107 ", javaLib "+JavaNativeLibraryBasename+"]";
108 }
109 }
110
111 /**
112 * {@link ImplementationIdentifier} for direct_bt implementation: {@value}
113 * <p>
114 * This value is exposed for convenience, user implementations are welcome.
115 * </p>
116 */
117 public static final ImplementationIdentifier DirectBTImplementationID = new ImplementationIdentifier("jau.direct_bt.DBTManager", "direct_bt", "javadirect_bt");
118
119 private static final List<ImplementationIdentifier> implIDs = new ArrayList<ImplementationIdentifier>();
120
121 /**
122 * Manifest's {@link Attributes.Name#SPECIFICATION_VERSION} or {@code null} if not available.
123 */
124 public static final String getAPIVersion() { return APIVersion; }
125 private static String APIVersion;
126
127 /**
128 * Manifest's {@link Attributes.Name#IMPLEMENTATION_VERSION} or {@code null} if not available.
129 */
130 public static final String getImplVersion() { return ImplVersion; }
131 private static String ImplVersion;
132
133 /**
134 * Verbose logging enabled or disabled.
135 * <p>
136 * System property {@code org.direct_bt.verbose}, boolean, default {@code false}.
137 * </p>
138 */
139 public static final boolean VERBOSE;
140
141 /**
142 * Debug logging enabled or disabled.
143 * <p>
144 * System property {@code org.direct_bt.debug}, boolean, default {@code false}.
145 * </p>
146 */
147 public static final boolean DEBUG;
148
149 /**
150 * True if jaulib {@link org.jau.sys.PlatformProps} has been detected.
151 */
152 public static final boolean JAULIB_AVAILABLE;
153
154 /**
155 * True if jaulib {@link #JAULIB_AVAILABLE} and its {@link org.jau.sys.PlatformProps#USE_TEMP_JAR_CACHE} is true,
156 * i.e. the jar cache is available, enabled and in use.
157 */
158 public static final boolean JAULIB_JARCACHE_USED;
159
160 /**
161 * Deprecated call to {@link java.security.AccessController#doPrivileged(PrivilegedAction)} w/o warnings.
162 * @param <T>
163 * @param o
164 * @return
165 */
166 @SuppressWarnings({ "deprecation", "removal" })
167 public static <T> T doPrivileged(final PrivilegedAction<T> o) {
168 return java.security.AccessController.doPrivileged( o );
169 }
170
171 static {
172 {
173 final String v = System.getProperty("org.direct_bt.debug", "false");
174 DEBUG = Boolean.valueOf(v);
175 }
176 if( DEBUG ) {
177 VERBOSE = true;
178 } else {
179 final String v = System.getProperty("org.direct_bt.verbose", "false");
180 VERBOSE = Boolean.valueOf(v);
181 }
182 implIDs.add(DirectBTImplementationID);
183
184 boolean isJaulibAvail = false;
185 try {
186 isJaulibAvail = null != Class.forName("org.jau.sys.RuntimeProps", true /* initializeClazz */, BTFactory.class.getClassLoader());
187 } catch( final Throwable t ) {
188 if( DEBUG ) {
189 System.err.println("BTFactory Caught: "+t.getMessage());
190 t.printStackTrace();
191 }
192 }
193 JAULIB_AVAILABLE = isJaulibAvail;
194
195 if( isJaulibAvail ) {
196 JAULIB_JARCACHE_USED = org.jau.sys.RuntimeProps.USE_TEMP_JAR_CACHE;
197 } else {
198 JAULIB_JARCACHE_USED = false;
199 }
200 if( VERBOSE ) {
201 System.err.println("Jaulib available: "+JAULIB_AVAILABLE+", JarCache in use: "+JAULIB_JARCACHE_USED);
202 }
203 }
204
205 private static AtomicReference<ImplementationIdentifier> initializedID = new AtomicReference<ImplementationIdentifier>(null);
206
207 public static void checkInitialized() {
208 if( null == initializedID.get() ) {
209 throw new IllegalStateException("Direct-BT not initialized.");
210 }
211 }
212 public static boolean isInitialized() {
213 return null != initializedID.get();
214 }
215
216 private static synchronized void initLibrary(final ImplementationIdentifier id) {
217 if( null != initializedID.get() ) {
218 if( id != initializedID.get() ) {
219 throw new IllegalStateException("Direct-BT already initialized with "+initializedID.get()+", can't override by "+id);
220 }
221 return;
222 }
223
224 final ClassLoader cl = BTFactory.class.getClassLoader();
225 boolean libsLoaded = false;
226 if( JAULIB_AVAILABLE ) {
228 try {
229 org.jau.pkg.JNIJarLibrary.addNativeJarLibs(new Class<?>[] { BTFactory.class }, null);
230 } catch (final Exception e0) {
231 System.err.println("BTFactory Caught "+e0.getClass().getSimpleName()+": "+e0.getMessage()+", while JNILibLoaderBase.addNativeJarLibs(..)");
232 if( DEBUG ) {
233 e0.printStackTrace();
234 }
235 }
236 }
237 try {
238 if( null != org.jau.sys.dl.NativeLibrary.open(id.ImplementationNativeLibraryBasename,
239 true /* searchSystemPath */, false /* searchSystemPathFirst */, cl, true /* global */) )
240 {
241 org.jau.sys.JNILibrary.loadLibrary(id.JavaNativeLibraryBasename, false, cl);
242 libsLoaded = true;
243 }
244 } catch (final Throwable t) {
245 System.err.println("Caught "+t.getClass().getSimpleName()+": "+t.getMessage()+", while loading libs..");
246 if( DEBUG ) {
247 t.printStackTrace();
248 }
249 }
250 if( DEBUG ) {
251 System.err.println("Jaulib: Native libs loaded: "+ libsLoaded);
252 }
253 }
254 if( !libsLoaded ) {
255 try {
256 final Throwable[] t = { null };
257 if( !PlatformToolkit.loadLibrary(id.ImplementationNativeLibraryBasename, cl, t) ) {
258 throw new RuntimeException("Couldn't load native library with basename <"+id.ImplementationNativeLibraryBasename+">", t[0]);
259 }
260 if( !PlatformToolkit.loadLibrary(id.JavaNativeLibraryBasename, cl, t) ) {
261 throw new RuntimeException("Couldn't load native library with basename <"+id.JavaNativeLibraryBasename+">", t[0]);
262 }
263 } catch (final Throwable e) {
264 System.err.println("Caught "+e.getClass().getSimpleName()+": "+e.getMessage()+", while loading libs (2) ..");
265 if( DEBUG ) {
266 e.printStackTrace();
267 }
268 throw e; // fwd exception - end here
269 }
270 }
271
272 // Map all Java properties '[org.]direct_bt.*' and 'direct_bt.*' to native environment.
273 try {
274 if( DEBUG ) {
275 System.err.println("BlootoothFactory: Mapping '[org.|jau.]direct_bt.*' properties to native environment");
276 }
277 final Properties props = doPrivileged(new PrivilegedAction<Properties>() {
278 @Override
279 public Properties run() {
280 return System.getProperties();
281 } });
282
283 final Enumeration<?> enums = props.propertyNames();
284 while (enums.hasMoreElements()) {
285 final String key = (String) enums.nextElement();
286 if( key.startsWith("org.direct_bt.") || key.startsWith("jau.direct_bt.") ||
287 key.startsWith("direct_bt.") )
288 {
289 final String value = props.getProperty(key);
290 if( DEBUG ) {
291 System.err.println(" <"+key+"> := <"+value+">");
292 }
293 setenv(key, value, true /* overwrite */);
294 }
295 }
296 } catch (final Throwable e) {
297 System.err.println("Caught exception while forwarding system properties: "+e.getMessage());
298 e.printStackTrace();
299 }
300
301 try {
302 final Manifest manifest = getManifest(cl, new String[] { "org.direct_bt" } );
303 final Attributes mfAttributes = null != manifest ? manifest.getMainAttributes() : null;
304
305 // major.minor must match!
306 final String NAPIVersion = getNativeAPIVersion();
307 final String JAPIVersion = null != mfAttributes ? mfAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION) : null;
308 if ( null != JAPIVersion && JAPIVersion.equals(NAPIVersion) == false) {
309 final String[] NAPIVersionCode = NAPIVersion.split("\\D");
310 final String[] JAPIVersionCode = JAPIVersion.split("\\D");
311 if (JAPIVersionCode[0].equals(NAPIVersionCode[0]) == false) {
312 if (Integer.valueOf(JAPIVersionCode[0]) < Integer.valueOf(NAPIVersionCode[0])) {
313 throw new RuntimeException("Java library "+JAPIVersion+" < native library "+NAPIVersion+". Please update the Java library.");
314 } else {
315 throw new RuntimeException("Native library "+NAPIVersion+" < java library "+JAPIVersion+". Please update the native library.");
316 }
317 } else if (JAPIVersionCode[1].equals(NAPIVersionCode[1]) == false) {
318 if (Integer.valueOf(JAPIVersionCode[1]) < Integer.valueOf(NAPIVersionCode[1])) {
319 throw new RuntimeException("Java library "+JAPIVersion+" < native library "+NAPIVersion+". Please update the Java library.");
320 } else {
321 throw new RuntimeException("Native library "+NAPIVersion+" < java library "+JAPIVersion+". Please update the native library.");
322 }
323 }
324 }
325 initializedID.set( id ); // initialized!
326
327 APIVersion = JAPIVersion;
328 ImplVersion = null != mfAttributes ? mfAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION) : null;
329 if( VERBOSE ) {
330 System.err.println("Direct-BT loaded "+id);
331 System.err.println("Direct-BT java api version "+JAPIVersion);
332 System.err.println("Direct-BT native api version "+NAPIVersion);
333 if( null != mfAttributes ) {
334 final Attributes.Name[] versionAttributeNames = new Attributes.Name[] {
335 Attributes.Name.SPECIFICATION_TITLE,
336 Attributes.Name.SPECIFICATION_VENDOR,
337 Attributes.Name.SPECIFICATION_VERSION,
338 Attributes.Name.IMPLEMENTATION_TITLE,
339 Attributes.Name.IMPLEMENTATION_VENDOR,
340 Attributes.Name.IMPLEMENTATION_VERSION,
341 new Attributes.Name("Implementation-Commit") };
342 for( final Attributes.Name an : versionAttributeNames ) {
343 System.err.println(" "+an+": "+mfAttributes.getValue(an));
344 }
345 } else {
346 System.err.println(" No Manifest available;");
347 }
348 }
349 } catch (final Throwable e) {
350 System.err.println("Error querying manifest information.");
351 e.printStackTrace();
352 throw e; // fwd exception - end here
353 }
354 }
355
356 private static synchronized BTManager getBTManager(final Class<?> factoryImplClass)
357 throws BTException, NoSuchMethodException, SecurityException,
358 IllegalAccessException, IllegalArgumentException, InvocationTargetException
359 {
360 final Method m = factoryImplClass.getMethod("getManager");
361 return (BTManager)m.invoke(null);
362 }
363
364 /**
365 * Registers a new {@link ImplementationIdentifier} to the internal list.
366 * The {@code id} is only added if not registered yet.
367 * @param id the {@link ImplementationIdentifier} to register
368 * @return {@code true} if the given {@link ImplementationIdentifier} has been newly added,
369 * otherwise {@code false}.
370 */
371 public static synchronized boolean registerImplementationIdentifier(final ImplementationIdentifier id) {
372 if( null == id ) {
373 return false;
374 }
375 if( implIDs.contains(id) ) {
376 return false;
377 }
378 return implIDs.add(id);
379 }
380
381 /**
382 * Returns the matching {@link ImplementationIdentifier} from the internal list or {@code null} if not found.
383 * @param fqBluetoothManagerImplementationClassName fully qualified class name for the {@link BTManager} implementation
384 */
385 public static synchronized ImplementationIdentifier getImplementationIdentifier(final String fqBluetoothManagerImplementationClassName) {
386 for(final ImplementationIdentifier id : implIDs) {
387 if( id.BluetoothManagerClassName.equals(fqBluetoothManagerImplementationClassName) ) {
388 return id;
389 }
390 }
391 return null;
392 }
393
394 /**
395 * Returns an initialized BluetoothManager instance using the given {@code fqBluetoothManagerImplementationClassName}
396 * to lookup a registered {@link ImplementationIdentifier}.
397 * <p>
398 * If found, method returns {@link #getBTManager(ImplementationIdentifier)}, otherwise {@code null}.
399 * </p>
400 * <p>
401 * The chosen implementation can't be changed within a running implementation, an exception is thrown if tried.
402 * </p>
403 *
404 * @param fqBluetoothManagerImplementationClassName fully qualified class name for the {@link BTManager} implementation
405 * @throws BTException
406 * @throws NoSuchMethodException
407 * @throws SecurityException
408 * @throws IllegalAccessException
409 * @throws IllegalArgumentException
410 * @throws InvocationTargetException
411 * @throws ClassNotFoundException
412 * @see {@link #DBusFactoryImplClassName}
413 * @see {@link #DirectBTFactoryImplClassName}
414 */
415 public static synchronized BTManager getBTManager(final String fqBluetoothManagerImplementationClassName)
416 throws BTException, NoSuchMethodException, SecurityException,
417 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
418 {
419 final ImplementationIdentifier id = getImplementationIdentifier(fqBluetoothManagerImplementationClassName);
420 if( null != id ) {
421 return getBTManager(id);
422 }
423 return null;
424 }
425
426 /**
427 * Returns an initialized BluetoothManager instance using the given {@link ImplementationIdentifier}.
428 * <p>
429 * If the {@link ImplementationIdentifier} has not been {@link #registerImplementationIdentifier(ImplementationIdentifier)},
430 * it will be added to the list.
431 * </p>
432 * <p>
433 * The chosen implementation can't be changed within a running implementation, an exception is thrown if tried.
434 * </p>
435 * @param id the specific {@link ImplementationIdentifier}
436 * @throws BTException
437 * @throws NoSuchMethodException
438 * @throws SecurityException
439 * @throws IllegalAccessException
440 * @throws IllegalArgumentException
441 * @throws InvocationTargetException
442 * @throws ClassNotFoundException
443 * @see {@link #DBusFactoryImplClassName}
444 * @see {@link #DirectBTFactoryImplClassName}
445 */
446 public static synchronized BTManager getBTManager(final ImplementationIdentifier id)
447 throws BTException, NoSuchMethodException, SecurityException,
448 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
449 {
451 initLibrary(id);
452 final Class<?> factoryImpl = Class.forName(id.BluetoothManagerClassName);
453 return getBTManager(factoryImpl);
454 }
455
456 /**
457 * Returns an initialized BluetoothManager instance using the DirectBT implementation.
458 * <p>
459 * Issues {@link #getBTManager(ImplementationIdentifier)} using {@link #DirectBTImplementationID}.
460 * </p>
461 * <p>
462 * The chosen implementation can't be changed within a running implementation, an exception is thrown if tried.
463 * </p>
464 * @throws BTException
465 * @throws NoSuchMethodException
466 * @throws SecurityException
467 * @throws IllegalAccessException
468 * @throws IllegalArgumentException
469 * @throws InvocationTargetException
470 * @throws ClassNotFoundException
471 */
472 public static synchronized BTManager getDirectBTManager()
473 throws BTException, NoSuchMethodException, SecurityException,
474 IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException
475 {
476 return getBTManager(DirectBTImplementationID);
477 }
478
479 /**
480 * Preloads the DirectBT native library w/o instantiating BTManager.
481 */
482 public static synchronized void initDirectBTLibrary() {
483 initLibrary(DirectBTImplementationID);
484 }
485
486 /**
487 * Helper function to retrieve a Manifest instance.
488 */
489 public static final Manifest getManifest(final ClassLoader cl, final String[] extensions) {
490 final Manifest[] extManifests = new Manifest[extensions.length];
491 try {
492 final Enumeration<URL> resources = cl.getResources("META-INF/MANIFEST.MF");
493 while (resources.hasMoreElements()) {
494 final URL resURL = resources.nextElement();
495 if( DEBUG ) {
496 System.err.println("resource: "+resURL);
497 }
498 final InputStream is = resURL.openStream();
499 final Manifest manifest;
500 try {
501 manifest = new Manifest(is);
502 } finally {
503 try {
504 is.close();
505 } catch (final IOException e) {}
506 }
507 final Attributes attributes = manifest.getMainAttributes();
508 if(attributes != null) {
509 final String attributesExtName = attributes.getValue( Attributes.Name.EXTENSION_NAME );
510 for(int i=0; i < extensions.length && null == extManifests[i]; i++) {
511 final String extension = extensions[i];
512 if( extension.equals( attributesExtName ) ) {
513 if( 0 == i ) {
514 return manifest; // 1st one has highest prio - done
515 }
516 extManifests[i] = manifest;
517 }
518 }
519 }
520 }
521 } catch (final IOException ex) {
522 throw new RuntimeException("Unable to read manifest.", ex);
523 }
524 for(int i=1; i<extManifests.length; i++) {
525 if( null != extManifests[i] ) {
526 return extManifests[i];
527 }
528 }
529 return null;
530 }
531
532 public static void main(final String args[]) {
533 System.err.println("Jaulib: Available "+JAULIB_AVAILABLE+", JarCache in use "+JAULIB_JARCACHE_USED);
534 if( JAULIB_AVAILABLE ) {
535 System.err.println(VersionUtil.getPlatformInfo());
536 System.err.println("Version Info:");
538 System.err.println(v);
539 System.err.println("");
540 System.err.println("Full Manifest:");
541 System.err.println(v.getFullManifestInfo(null));
542 } else {
543 System.err.println("Full Manifest:");
544 final Manifest manifest = getManifest(BTFactory.class.getClassLoader(), new String[] { "org.direct_bt" } );
545 final Attributes attr = manifest.getMainAttributes();
546 final Set<Object> keys = attr.keySet();
547 final StringBuilder sb = new StringBuilder();
548 for(final Iterator<Object> iter=keys.iterator(); iter.hasNext(); ) {
549 final Attributes.Name key = (Attributes.Name) iter.next();
550 final String val = attr.getValue(key);
551 sb.append(" ");
552 sb.append(key);
553 sb.append(" = ");
554 sb.append(val);
555 sb.append(System.lineSeparator());
556 }
557 System.err.println(sb);
558 }
559 try {
560 final BTManager mngr = getDirectBTManager();
561 final List<BTAdapter> adapters = mngr.getAdapters();
562 System.err.println("BTManager: adapters "+adapters.size());
563 int i=0;
564 for(final Iterator<BTAdapter> iter = adapters.iterator(); iter.hasNext(); ++i) {
565 System.err.println("BTAdapter["+i+"]: "+iter.next().toString()); // has full toString()
566 }
567 } catch (BTException | NoSuchMethodException | SecurityException
568 | IllegalAccessException | IllegalArgumentException
569 | InvocationTargetException | ClassNotFoundException e) {
570 e.printStackTrace();
571 }
572 }
573
574 public native static String getNativeVersion();
575 public native static String getNativeAPIVersion();
576 private native static void setenv(String name, String value, boolean overwrite);
577}
578
579/** \example DBTScanner10.java
580 * This Java scanner {@link BTRole::Master} GATT client example uses an event driven workflow
581 * and multithreading, i.e. one thread processes each found device when notified.
582 * <p>
583 * This example represents the recommended utilization of Direct-BT.
584 * </p>
585 * <p>
586 * See `dbt_scanner10.cpp` for invocation examples, since both apps are fully compatible.
587 * </p>
588 */
589
590/** \example DBTPeripheral00.java
591 * This Java peripheral {@link BTRole::Slave} GATT server example uses an event driven workflow.
592 * <p>
593 * See `dbt_peripheral00.cpp` for invocation examples, since both apps are fully compatible.
594 * </p>
595 */
596
597/** \example TestDBTClientServer00.java
598 * Unit test, trial using actual BT adapter.
599 *
600 * Basic client and server Bluetooth tests, requiring one BT adapter:
601 * - start server advertising
602 * - server stop advertising
603 * - reuse server-adapter for client-mode discovery (just toggle on/off)
604 */
605
606/** \example TestDBTClientServer10.java
607 * Unit test, trial using actual BT adapter.
608 *
609 * Testing a full Bluetooth server and client lifecycle of operations, requiring two BT adapter:
610 * - start server advertising
611 * - start client discovery and connect to server when discovered
612 * - client/server processing of connection when ready
613 * - client disconnect
614 * - server stop advertising
615 * - security-level: NONE, ENC_ONLY freshly-paired and ENC_ONLY pre-paired
616 * - reuse server-adapter for client-mode discovery (just toggle on/off)
617 */
Identifier names, allowing BTFactory#getBTManager(ImplementationIdentifier) to initialize the require...
Definition: BTFactory.java:64
final String JavaNativeLibraryBasename
Native library basename for the Java binding native library.
Definition: BTFactory.java:78
final String ImplementationNativeLibraryBasename
Native library basename for the implementation native library.
Definition: BTFactory.java:76
ImplementationIdentifier(final String BluetoothManagerClassName, final String ImplementationNativeLibraryBasename, final String JavaNativeLibraryBasename)
Definition: BTFactory.java:80
final String BluetoothManagerClassName
Fully qualified class name for the BTManager implementation.
Definition: BTFactory.java:74
One stop BTManager API entry point.
Definition: BTFactory.java:52
static synchronized BTManager getBTManager(final String fqBluetoothManagerImplementationClassName)
Returns an initialized BluetoothManager instance using the given fqBluetoothManagerImplementationClas...
Definition: BTFactory.java:415
static final boolean VERBOSE
Verbose logging enabled or disabled.
Definition: BTFactory.java:139
static native String getNativeVersion()
static synchronized BTManager getBTManager(final ImplementationIdentifier id)
Returns an initialized BluetoothManager instance using the given ImplementationIdentifier.
Definition: BTFactory.java:446
static synchronized boolean registerImplementationIdentifier(final ImplementationIdentifier id)
Registers a new ImplementationIdentifier to the internal list.
Definition: BTFactory.java:371
static void main(final String args[])
Definition: BTFactory.java:532
static void checkInitialized()
Definition: BTFactory.java:207
static final boolean DEBUG
Debug logging enabled or disabled.
Definition: BTFactory.java:147
static final boolean JAULIB_JARCACHE_USED
True if jaulib JAULIB_AVAILABLE and its org.jau.sys.PlatformProps#USE_TEMP_JAR_CACHE is true,...
Definition: BTFactory.java:158
static synchronized ImplementationIdentifier getImplementationIdentifier(final String fqBluetoothManagerImplementationClassName)
Returns the matching ImplementationIdentifier from the internal list or null if not found.
Definition: BTFactory.java:385
static final ImplementationIdentifier DirectBTImplementationID
ImplementationIdentifier for direct_bt implementation: {@value}
Definition: BTFactory.java:117
static final String getImplVersion()
Manifest's Attributes.Name#IMPLEMENTATION_VERSION or null if not available.
Definition: BTFactory.java:130
static boolean isInitialized()
Definition: BTFactory.java:212
static final String getAPIVersion()
Manifest's Attributes.Name#SPECIFICATION_VERSION or null if not available.
Definition: BTFactory.java:124
static native String getNativeAPIVersion()
static synchronized void initDirectBTLibrary()
Preloads the DirectBT native library w/o instantiating BTManager.
Definition: BTFactory.java:482
static final Manifest getManifest(final ClassLoader cl, final String[] extensions)
Helper function to retrieve a Manifest instance.
Definition: BTFactory.java:489
static final boolean JAULIB_AVAILABLE
True if jaulib org.jau.sys.PlatformProps has been detected.
Definition: BTFactory.java:152
static synchronized BTManager getDirectBTManager()
Returns an initialized BluetoothManager instance using the DirectBT implementation.
Definition: BTFactory.java:472
static< T > T doPrivileged(final PrivilegedAction< T > o)
Deprecated call to java.security.AccessController#doPrivileged(PrivilegedAction) w/o warnings.
Definition: BTFactory.java:167
This jaulib derived version info class is only usable when having jaulib available,...
static DirectBTVersion getInstance()
Returns a transient new instance.
A thread safe singleton handler of the BTAdapter manager, e.g.
Definition: BTManager.java:36
List< BTAdapter > getAdapters()
Returns a list of BluetoothAdapters available in the system.