├── .github
└── FUNDING.yml
├── .gitignore
├── BluetoothClassicLibrary
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── github
│ └── douglasjunior
│ └── bluetoothclassiclibrary
│ ├── BluetoothClassicService.java
│ ├── BluetoothConfiguration.java
│ ├── BluetoothDeviceDecorator.java
│ ├── BluetoothDeviceDecoratorNull.java
│ ├── BluetoothService.java
│ ├── BluetoothStatus.java
│ └── BluetoothWriter.java
├── BluetoothLowEnergyLibrary
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── github
│ └── douglasjunior
│ └── bluetoothlowenergylibrary
│ └── BluetoothLeService.java
├── LICENSE
├── README.md
├── Sample
├── build.gradle
├── libs
│ ├── print_lib_0.13.jar
│ └── zxing.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── github
│ │ └── douglasjunior
│ │ └── bluetoothsample
│ │ ├── BitmapActivity.java
│ │ ├── BitmapHelper.java
│ │ ├── DeviceActivity.java
│ │ ├── DeviceItemAdapter.java
│ │ ├── EscPosHelper.java
│ │ ├── MainActivity.java
│ │ └── SampleApplication.java
│ └── res
│ ├── drawable
│ ├── bmw.jpg
│ ├── jac.JPG
│ ├── loading.jpg
│ └── palio.jpg
│ ├── layout
│ ├── activity_bitmap.xml
│ ├── activity_device.xml
│ ├── activity_main.xml
│ └── device_item.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── values-v21
│ └── styles.xml
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── SampleKotlin
├── .gitignore
├── build.gradle
├── libs
│ ├── print_lib_0.13.jar
│ └── zxing.jar
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── github
│ │ └── douglasjunior
│ │ └── bluetoothsamplekotlin
│ │ ├── BitmapActivity.java
│ │ ├── BitmapHelper.java
│ │ ├── DeviceActivity.java
│ │ ├── DeviceItemAdapter.java
│ │ ├── EscPosHelper.java
│ │ ├── MainActivity.kt
│ │ └── SampleApplication.kt
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ ├── bmw.jpg
│ ├── ic_launcher_background.xml
│ ├── jac.JPG
│ ├── loading.jpg
│ └── palio.jpg
│ ├── layout
│ ├── activity_bitmap.xml
│ ├── activity_device.xml
│ ├── activity_main.xml
│ └── device_item.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: douglasjunior
4 | patreon: douglasjunior # Replace with a single Patreon username
5 | custom: paypal.me/douglasnassif
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea
5 | .DS_Store
6 | **/build
7 | /captures
8 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '25.0.0'
6 | defaultConfig {
7 | minSdkVersion 7
8 | targetSdkVersion 7
9 | versionCode 11
10 | versionName "0.3.5"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | compileOptions {
19 | sourceCompatibility JavaVersion.VERSION_1_7
20 | targetCompatibility JavaVersion.VERSION_1_7
21 | }
22 | productFlavors {
23 | }
24 | }
25 |
26 | dependencies {
27 | compile 'com.android.support:support-annotations:25.0.0'
28 | }
29 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:/ferramentas/adt-bundle-windows-x86_64-20140702/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothClassicService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | /*
26 | * Copyright (C) 2009 The Android Open Source Project
27 | *
28 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
29 | * the License. You may obtain a copy of the License at
30 | *
31 | * http://www.apache.org/licenses/LICENSE-2.0
32 | *
33 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
34 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
35 | * specific language governing permissions and limitations under the License.
36 | */
37 |
38 | package com.github.douglasjunior.bluetoothclassiclibrary;
39 |
40 | import android.Manifest;
41 | import android.bluetooth.BluetoothAdapter;
42 | import android.bluetooth.BluetoothDevice;
43 | import android.bluetooth.BluetoothSocket;
44 | import android.content.BroadcastReceiver;
45 | import android.content.Context;
46 | import android.content.Intent;
47 | import android.content.IntentFilter;
48 | import android.media.AudioManager;
49 | import android.support.annotation.RequiresPermission;
50 | import android.util.Log;
51 |
52 | import java.io.InputStream;
53 | import java.io.OutputStream;
54 |
55 | /**
56 | * Code adapted from Android Open Source Project
57 | */
58 | public class BluetoothClassicService extends BluetoothService {
59 |
60 | private static final String TAG = BluetoothClassicService.class.getSimpleName();
61 |
62 | // Unique UUID for this application
63 | //private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
64 |
65 | // Member fields
66 | private final BluetoothAdapter mAdapter;
67 | private ConnectThread mConnectThread;
68 | private ConnectedThread mConnectedThread;
69 |
70 | protected BluetoothClassicService(BluetoothConfiguration config) {
71 | super(config);
72 | mAdapter = BluetoothAdapter.getDefaultAdapter();
73 | mStatus = BluetoothStatus.NONE;
74 | }
75 |
76 |
77 | /**
78 | * Start the ConnectThread to initiate a connection to a remote device.
79 | *
80 | * @param device The BluetoothDevice to connect
81 | */
82 | @RequiresPermission(Manifest.permission.BLUETOOTH)
83 | public synchronized void connect(BluetoothDevice device) {
84 | if (D)
85 | Log.d(TAG, "connect to: " + device);
86 |
87 | disconnect();
88 |
89 | // Start the thread to connect with the given device
90 | mConnectThread = new ConnectThread(device);
91 | mConnectThread.start();
92 | updateState(BluetoothStatus.CONNECTING);
93 | }
94 |
95 | @Override
96 | public void disconnect() {
97 | if (D)
98 | Log.d(TAG, "disconnect");
99 |
100 | // Cancel any thread attempting to make a connection
101 | if (mConnectThread != null) {
102 | mConnectThread.cancel();
103 | mConnectThread = null;
104 | }
105 |
106 | // Cancel any thread currently running a connection
107 | if (mConnectedThread != null) {
108 | mConnectedThread.cancel();
109 | mConnectedThread = null;
110 | }
111 | }
112 |
113 | /**
114 | * Start the ConnectedThread to begin managing a Bluetooth connection
115 | *
116 | * @param socket The BluetoothSocket on which the connection was made
117 | * @param device The BluetoothDevice that has been connected
118 | */
119 | @RequiresPermission(Manifest.permission.BLUETOOTH)
120 | private synchronized void connected(BluetoothSocket socket, final BluetoothDevice device) {
121 | if (D)
122 | Log.d(TAG, "connected");
123 |
124 | // Start the thread to manage the connection and perform transmissions
125 | mConnectedThread = new ConnectedThread(socket);
126 | mConnectedThread.start();
127 |
128 | // Send the name of the connected device back to the UI Activity
129 | if (onEventCallback != null)
130 | runOnMainThread(new Runnable() {
131 |
132 | @RequiresPermission(Manifest.permission.BLUETOOTH)
133 | @Override
134 | public void run() {
135 | onEventCallback.onDeviceName(device.getName());
136 | }
137 |
138 | });
139 |
140 | updateState(BluetoothStatus.CONNECTED);
141 | }
142 |
143 | /**
144 | * Stop all threads
145 | */
146 | public synchronized void stopService() {
147 | if (D)
148 | Log.d(TAG, "stop");
149 |
150 | disconnect();
151 |
152 | if (BluetoothService.mDefaultServiceInstance == this)
153 | BluetoothService.mDefaultServiceInstance = null;
154 | }
155 |
156 | /**
157 | * Required by BluetoothLeService.class and not supported in BluetoothClassicService.class.
158 | */
159 | @Override
160 | public void requestConnectionPriority(int connectionPriority) {
161 | throw new UnsupportedOperationException("requestConnectionPriority is a feature in Bluetooth Low Energy " +
162 | "and not supported in BluetoothClassic");
163 | }
164 |
165 | /**
166 | * Write to the ConnectedThread in an unsynchronized manner
167 | *
168 | * @param out The bytes to write
169 | * @see
170 | */
171 | public synchronized void write(byte[] out) {
172 | // Create temporary object
173 | ConnectedThread r;
174 | // Synchronize a copy of the ConnectedThread
175 |
176 | if (mStatus != BluetoothStatus.CONNECTED)
177 | return;
178 |
179 | r = mConnectedThread;
180 |
181 | // Perform the write unsynchronized
182 | r.write(out);
183 | }
184 |
185 | /**
186 | * Indicate that the connection attempt failed and notify the UI Activity.
187 | */
188 | private void connectionFailed() {
189 | updateState(BluetoothStatus.NONE);
190 |
191 | // Send a failure message back to the Activity
192 | if (onEventCallback != null)
193 | runOnMainThread(new Runnable() {
194 | @Override
195 | public void run() {
196 | onEventCallback.onToast("Could not connect to device");
197 | }
198 | });
199 | }
200 |
201 | /**
202 | * Indicate that the connection was lost and notify the UI Activity.
203 | */
204 | private void connectionLost() {
205 | updateState(BluetoothStatus.NONE);
206 |
207 | // Send a failure message back to the Activity
208 |
209 | if (onEventCallback != null)
210 | runOnMainThread(new Runnable() {
211 | @Override
212 | public void run() {
213 | onEventCallback.onToast("Connection lost");
214 | }
215 | });
216 | }
217 |
218 | /**
219 | * This thread runs while attempting to make an outgoing connection with a device. It runs straight through; the
220 | * connection either succeeds or fails.
221 | */
222 | private class ConnectThread extends Thread {
223 | private final BluetoothSocket mmSocket;
224 | private final BluetoothDevice mmDevice;
225 |
226 | @RequiresPermission(Manifest.permission.BLUETOOTH)
227 | public ConnectThread(BluetoothDevice device) {
228 | mmDevice = device;
229 | BluetoothSocket tmp = null;
230 |
231 | // Get a BluetoothSocket for a connection with the given BluetoothDevice
232 | try {
233 | tmp = device.createRfcommSocketToServiceRecord(mConfig.uuid);
234 | } catch (Exception e) {
235 | Log.e(TAG, "create() failed", e);
236 | }
237 | try {
238 | AudioManager mAudioManager = (AudioManager) mConfig.context.getSystemService(Context.AUDIO_SERVICE);
239 | //For phone speaker(loadspeaker)
240 | mAudioManager.setMode(AudioManager.MODE_NORMAL);
241 | mAudioManager.setBluetoothScoOn(false);
242 | mAudioManager.setSpeakerphoneOn(true);
243 | } catch (Exception ex) {
244 | ex.printStackTrace();
245 | }
246 | mmSocket = tmp;
247 | }
248 |
249 | @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN})
250 | public void run() {
251 | Log.i(TAG, "BEGIN mConnectThread");
252 | setName("ConnectThread");
253 |
254 | // Always cancel discovery because it will slow down a connection
255 | if (mAdapter.isDiscovering())
256 | mAdapter.cancelDiscovery();
257 |
258 | // Make a connection to the BluetoothSocket
259 | try {
260 | // This is a blocking call and will only return on a
261 | // successful connection or an exception
262 | mmSocket.connect();
263 | } catch (Exception e) {
264 | e.printStackTrace();
265 | connectionFailed();
266 | // Close the socket
267 | try {
268 | mmSocket.close();
269 | } catch (Exception e2) {
270 | Log.e(TAG, "unable to close() socket during connection failure", e2);
271 | }
272 | return;
273 | }
274 |
275 | // Reset the ConnectThread because we're done
276 | synchronized (BluetoothClassicService.this) {
277 | mConnectThread = null;
278 | }
279 |
280 | // Start the connected thread
281 | connected(mmSocket, mmDevice);
282 | }
283 |
284 | public void cancel() {
285 | try {
286 | mmSocket.close();
287 | } catch (Exception e) {
288 | Log.e(TAG, "close() of connect socket failed", e);
289 | }
290 | try {
291 | interrupt();
292 | } catch (Exception e) {
293 | Log.e(TAG, "interrupt() of Thread failed", e);
294 | }
295 | }
296 | }
297 |
298 | /**
299 | * This thread runs during a connection with a remote device. It handles all incoming and outgoing transmissions.
300 | */
301 | private class ConnectedThread extends Thread {
302 | private final BluetoothSocket mmSocket;
303 | private final InputStream mmInStream;
304 | private final OutputStream mmOutStream;
305 | private boolean canceled = false;
306 |
307 | public ConnectedThread(BluetoothSocket socket) {
308 | Log.d(TAG, "create ConnectedThread");
309 | mmSocket = socket;
310 | InputStream tmpIn = null;
311 | OutputStream tmpOut = null;
312 |
313 | // Get the BluetoothSocket input and output streams
314 | try {
315 | tmpIn = socket.getInputStream();
316 | tmpOut = socket.getOutputStream();
317 | } catch (Exception e) {
318 | Log.e(TAG, "temp sockets not created", e);
319 | }
320 |
321 | mmInStream = tmpIn;
322 | mmOutStream = tmpOut;
323 | }
324 |
325 | public void run() {
326 | Log.i(TAG, "BEGIN mConnectedThread");
327 | byte temp;
328 | final byte[] buffer = new byte[mConfig.bufferSize];
329 | int i = 0;
330 | byte byteDelimiter = (byte) mConfig.characterDelimiter;
331 | // Keep listening to the InputStream while connected
332 | while (!canceled) {
333 | try {
334 | // Read from the InputStream
335 | int read = mmInStream.read();
336 | temp = (byte) read;
337 |
338 | if (temp == byteDelimiter) {
339 | if (i > 0) {
340 | dispatchBuffer(buffer, i);
341 | i = 0;
342 | }
343 | continue;
344 | }
345 | if (i == buffer.length - 1) {
346 | dispatchBuffer(buffer, i);
347 | i = 0;
348 | }
349 | buffer[i] = temp;
350 | i++;
351 | //System.out.println("read: " + new String(buffer, 0 , i));
352 | } catch (Exception e) {
353 | Log.e(TAG, "disconnected", e);
354 | connectionLost();
355 | break;
356 | }
357 | }
358 |
359 | }
360 |
361 | private void dispatchBuffer(byte[] buffer, int i) {
362 | final byte[] data = new byte[i];
363 | System.arraycopy(buffer, 0, data, 0, i);
364 | if (onEventCallback != null) {
365 | runOnMainThread(new Runnable() {
366 | @Override
367 | public void run() {
368 | onEventCallback.onDataRead(data, data.length);
369 | }
370 | });
371 | }
372 | }
373 |
374 | /**
375 | * Write to the connected OutStream.
376 | *
377 | * @param buffer The bytes to write
378 | */
379 | public void write(final byte[] buffer) {
380 | try {
381 | mmOutStream.write(buffer);
382 | mmOutStream.flush();
383 |
384 | if (onEventCallback != null)
385 | runOnMainThread(new Runnable() {
386 | @Override
387 | public void run() {
388 | onEventCallback.onDataWrite(buffer);
389 | }
390 | });
391 | } catch (Exception e) {
392 | Log.e(TAG, "Exception during write", e);
393 | }
394 | }
395 |
396 | public void cancel() {
397 | canceled = true;
398 | try {
399 | mmSocket.close();
400 | } catch (Exception e) {
401 | Log.e(TAG, "close() of connect socket failed", e);
402 | }
403 | try {
404 | mmInStream.close();
405 | } catch (Exception e) {
406 | Log.e(TAG, "close() of connect socket failed", e);
407 | }
408 | try {
409 | interrupt();
410 | } catch (Exception e) {
411 | Log.e(TAG, "interrupt() of Thread failed", e);
412 | }
413 | }
414 | }
415 |
416 | // The BroadcastReceiver that listens for discovered devices and
417 | // changes the title when discovery is finished
418 | private final BroadcastReceiver mScanReceiver = new BroadcastReceiver() {
419 | @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH})
420 | @Override
421 | public void onReceive(Context context, Intent intent) {
422 | String action = intent.getAction();
423 |
424 | // When discovery finds a device
425 | if (BluetoothDevice.ACTION_FOUND.equals(action)) {
426 | // Get the BluetoothDevice object from the Intent
427 | final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
428 | // If it's already paired, skip it, because it's been listed
429 | // already
430 | final int RSSI = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
431 |
432 | if (onScanCallback != null)
433 | runOnMainThread(new Runnable() {
434 | @Override
435 | public void run() {
436 | onScanCallback.onDeviceDiscovered(device, RSSI);
437 | }
438 | });
439 | } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
440 | stopScan();
441 | }
442 | }
443 | };
444 |
445 | @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH})
446 | @Override
447 | public void startScan() {
448 | if (onScanCallback != null)
449 | runOnMainThread(new Runnable() {
450 | @Override
451 | public void run() {
452 | onScanCallback.onStartScan();
453 | }
454 | });
455 |
456 | // Register for broadcasts when a device is discovered
457 | IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
458 | mConfig.context.registerReceiver(mScanReceiver, filter);
459 |
460 | // Register for broadcasts when discovery has finished
461 | filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
462 | mConfig.context.registerReceiver(mScanReceiver, filter);
463 |
464 | if (mAdapter.isDiscovering()) {
465 | mAdapter.cancelDiscovery();
466 | }
467 |
468 | mAdapter.startDiscovery();
469 | }
470 |
471 | @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH})
472 | @Override
473 | public void stopScan() {
474 | try {
475 | mConfig.context.unregisterReceiver(mScanReceiver);
476 | } catch (IllegalArgumentException ex) {
477 | ex.printStackTrace();
478 | }
479 |
480 | if (mAdapter.isDiscovering()) {
481 | mAdapter.cancelDiscovery();
482 | }
483 |
484 | if (onScanCallback != null)
485 | runOnMainThread(new Runnable() {
486 | @Override
487 | public void run() {
488 | onScanCallback.onStopScan();
489 | }
490 | });
491 | }
492 |
493 | }
494 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | import android.bluetooth.BluetoothDevice;
28 | import android.content.Context;
29 | import android.os.Build;
30 | import android.util.Log;
31 | import android.bluetooth.BluetoothGatt;
32 |
33 | import java.util.UUID;
34 |
35 | /**
36 | * Created by dougl on 10/04/2017.
37 | */
38 | public class BluetoothConfiguration {
39 |
40 | private static final String TAG = BluetoothConfiguration.class.getSimpleName();
41 |
42 | /**
43 | * Class reference for the {@link BluetoothService} implementation.
44 | *
45 | * @see BluetoothClassicService
46 | * @see BluetoothLeService
47 | */
48 | public Class extends BluetoothService> bluetoothServiceClass;
49 |
50 | /**
51 | * {@link android.app.Application} context reference.
52 | */
53 | public Context context;
54 |
55 | /**
56 | * Name of your application or device.
57 | */
58 | public String deviceName;
59 |
60 | /**
61 | * Maximum of bytes to keep in the buffer before call the
62 | * {@link com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService.OnBluetoothEventCallback#onDataRead(byte[], int)}
63 | */
64 | public int bufferSize;
65 |
66 | /**
67 | * Character delimiter to know if a data is received completly and call the
68 | * {@link com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService.OnBluetoothEventCallback#onDataRead(byte[], int)}
69 | */
70 | public char characterDelimiter;
71 |
72 | /**
73 | * Required in {@link BluetoothClassicService}, is the UUID of the device that will connect in serial mode.
74 | * Optional in {@link BluetoothLeService}, is the UUID of the device that will be filtered in scan.
75 | * Set {@link null} if you want to scan all devices.
76 | */
77 | public UUID uuid;
78 |
79 | /**
80 | * Required for {@link BluetoothLeService}
81 | * UUID of bluetooth service.
82 | */
83 | public UUID uuidService;
84 |
85 | /**
86 | * Required for {@link BluetoothLeService}
87 | * UUID of bluetooth characteristic.
88 | */
89 | public UUID uuidCharacteristic;
90 |
91 | /**
92 | * Preferred transport for GATT connections to remote dual-mode devices
93 | * {@link BluetoothDevice#TRANSPORT_AUTO} or
94 | * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
95 | */
96 | public int transport;
97 |
98 | /**
99 | * Whether to call the listener only in Main Thread (true)
100 | * or call in the Thread where the event occurs (false).
101 | */
102 | public boolean callListenersInMainThread = true;
103 |
104 | /**
105 | * Required for {@link BluetoothLeService}
106 | * Request a specific connection priority. Must be one of
107 | * {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED}, {@link BluetoothGatt#CONNECTION_PRIORITY_HIGH}
108 | * or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
109 | *
110 | * An application should only request high priority connection parameters to transfer
111 | * large amounts of data over LE quickly. Once the transfer is complete, the application
112 | * should request {@link BluetoothGatt#CONNECTION_PRIORITY_BALANCED} connection parameters
113 | * to reduce energy use.
114 | */
115 | public int connectionPriority;
116 |
117 | public BluetoothConfiguration() {
118 | setDefaultTransport();
119 | }
120 |
121 | /**
122 | * Set the default value for {@link BluetoothConfiguration#transport}.
123 | */
124 | private void setDefaultTransport() {
125 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
126 | transport = BluetoothDevice.TRANSPORT_LE;
127 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
128 | // From Android LOLLIPOP (21) the transport types exists, but them are hide for use,
129 | // so is needed to use relfection to get the value
130 | try {
131 | transport = BluetoothDevice.class.getDeclaredField("TRANSPORT_LE").getInt(null);
132 | } catch (Exception ex) {
133 | Log.d(TAG, "Error on get BluetoothDevice.TRANSPORT_LE with reflection.", ex);
134 | }
135 | } else {
136 | transport = -1;
137 | }
138 | }
139 | }
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothDeviceDecorator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | import android.Manifest;
28 | import android.bluetooth.BluetoothDevice;
29 | import android.support.annotation.RequiresPermission;
30 |
31 | /**
32 | * Created by Douglas on 16/09/2014.
33 | */
34 | public class BluetoothDeviceDecorator {
35 |
36 | private BluetoothDevice mDevice;
37 | private int mRSSI;
38 |
39 | public BluetoothDeviceDecorator(BluetoothDevice device) {
40 | mDevice = device;
41 | }
42 |
43 | public BluetoothDeviceDecorator(BluetoothDevice device, int RSSI) {
44 | this(device);
45 | mRSSI = RSSI;
46 | }
47 |
48 | @RequiresPermission(Manifest.permission.BLUETOOTH)
49 | public String getName() {
50 | return mDevice.getName() != null && mDevice.getName().length() != 0 ? mDevice.getName() : "Desconhecido...";
51 | }
52 |
53 | public String getAddress() {
54 | return mDevice.getAddress();
55 | }
56 |
57 | public int getRSSI() {
58 | return mRSSI;
59 | }
60 |
61 | public void setRSSI(int RSSI) {
62 | mRSSI = RSSI;
63 | }
64 |
65 | @Override
66 | public boolean equals(Object o) {
67 | if (this == o) return true;
68 | if (o == null || getClass() != o.getClass()) return false;
69 |
70 | BluetoothDeviceDecorator that = (BluetoothDeviceDecorator) o;
71 |
72 | return mDevice.equals(that.mDevice);
73 | }
74 |
75 | @Override
76 | public int hashCode() {
77 | return mDevice.hashCode();
78 | }
79 |
80 | public void setDevice(BluetoothDevice device) {
81 | this.mDevice = device;
82 | }
83 |
84 | public BluetoothDevice getDevice() {
85 | return mDevice;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothDeviceDecoratorNull.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | import android.bluetooth.BluetoothDevice;
28 |
29 | /**
30 | * Created by Douglas on 16/09/2014.
31 | */
32 | public class BluetoothDeviceDecoratorNull extends BluetoothDeviceDecorator {
33 |
34 | private BluetoothDeviceDecoratorNull(BluetoothDevice device) {
35 | super(device);
36 | }
37 |
38 | public static BluetoothDeviceDecoratorNull getInstance() {
39 | return new BluetoothDeviceDecoratorNull(null);
40 | }
41 |
42 | @Override
43 | public String getName() {
44 | return "No device found";
45 | }
46 |
47 | @Override
48 | public String getAddress() {
49 | return "";
50 | }
51 |
52 | @Override
53 | public int getRSSI() {
54 | return 9999;
55 | }
56 |
57 | @Override
58 | public void setRSSI(int RSSI) {
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | import android.bluetooth.BluetoothDevice;
28 | import android.os.Handler;
29 | import android.util.Log;
30 |
31 | import java.lang.reflect.Constructor;
32 | import java.lang.reflect.InvocationTargetException;
33 |
34 | /**
35 | * Created by douglas on 23/03/15.
36 | */
37 | public abstract class BluetoothService {
38 | // Debugging
39 | private static final String TAG = BluetoothService.class.getSimpleName();
40 | protected static final boolean D = true;
41 |
42 | protected static BluetoothService mDefaultServiceInstance;
43 | protected BluetoothConfiguration mConfig;
44 | protected BluetoothStatus mStatus;
45 |
46 | private final Handler handler;
47 |
48 | protected OnBluetoothEventCallback onEventCallback;
49 |
50 | protected OnBluetoothScanCallback onScanCallback;
51 |
52 | private static BluetoothConfiguration mDefaultConfiguration;
53 |
54 | protected BluetoothService(BluetoothConfiguration config) {
55 | this.mConfig = config;
56 | this.mStatus = BluetoothStatus.NONE;
57 | this.handler = new Handler();
58 | }
59 |
60 | public void setOnEventCallback(OnBluetoothEventCallback onEventCallback) {
61 | this.onEventCallback = onEventCallback;
62 | }
63 |
64 | public void setOnScanCallback(OnBluetoothScanCallback onScanCallback) {
65 | this.onScanCallback = onScanCallback;
66 | }
67 |
68 | public BluetoothConfiguration getConfiguration() {
69 | return mConfig;
70 | }
71 |
72 | protected synchronized void updateState(final BluetoothStatus status) {
73 | Log.v(TAG, "updateStatus() " + mStatus + " -> " + status);
74 | mStatus = status;
75 |
76 | // Give the new state to the Handler so the UI Activity can update
77 | if (onEventCallback != null)
78 | runOnMainThread(new Runnable() {
79 | @Override
80 | public void run() {
81 | onEventCallback.onStatusChange(status);
82 | }
83 | });
84 | }
85 |
86 | protected void runOnMainThread(final Runnable runnable, final long delayMillis) {
87 | if (mConfig.callListenersInMainThread) {
88 | if (delayMillis > 0) {
89 | handler.postDelayed(runnable, delayMillis);
90 | } else {
91 | handler.post(runnable);
92 | }
93 | } else {
94 | if (delayMillis > 0) {
95 | new Thread() {
96 | @Override
97 | public void run() {
98 | try {
99 | Thread.sleep(delayMillis);
100 | runnable.run();
101 | } catch (InterruptedException e) {
102 | e.printStackTrace();
103 | }
104 | }
105 | }.start();
106 | } else {
107 | runnable.run();
108 | }
109 | }
110 | }
111 |
112 | protected void runOnMainThread(Runnable runnable) {
113 | runOnMainThread(runnable, 0);
114 | }
115 |
116 | protected void removeRunnableFromHandler(Runnable runnable) {
117 | if (handler != null) {
118 | handler.removeCallbacks(runnable);
119 | }
120 | }
121 |
122 | /**
123 | * Current BluetoothService status.
124 | *
125 | * @return
126 | */
127 | public synchronized BluetoothStatus getStatus() {
128 | return mStatus;
129 | }
130 |
131 | /**
132 | * Start scan process and call the {@link OnBluetoothScanCallback}
133 | */
134 | public abstract void startScan();
135 |
136 | /**
137 | * Stop scan process and call the {@link OnBluetoothScanCallback}
138 | */
139 | public abstract void stopScan();
140 |
141 | /**
142 | * Try to connect to the device and call the {@link OnBluetoothEventCallback}
143 | */
144 | public abstract void connect(BluetoothDevice device);
145 |
146 | /**
147 | * Try to disconnect to the device and call the {@link OnBluetoothEventCallback}
148 | */
149 | public abstract void disconnect();
150 |
151 | /**
152 | * Write a array of bytes to the connected device.
153 | */
154 | public abstract void write(byte[] bytes);
155 |
156 | /**
157 | * Stops the BluetoothService and turn it unusable.
158 | */
159 | public abstract void stopService();
160 |
161 | /**
162 | * Request the connection priority.
163 | */
164 | public abstract void requestConnectionPriority(int connectionPriority);
165 |
166 | /* ====================================
167 | STATICS METHODS
168 | ====================================== */
169 |
170 | /**
171 | * Use {@link BluetoothService#init(BluetoothConfiguration)} instead.
172 | *
173 | * @param config
174 | */
175 | @Deprecated
176 | public static void setDefaultConfiguration(BluetoothConfiguration config) {
177 | init(config);
178 | }
179 |
180 | /**
181 | * Configures and initialize the BluetoothService singleton instance.
182 | *
183 | * @param config
184 | */
185 | public static void init(BluetoothConfiguration config) {
186 | mDefaultConfiguration = config;
187 | if (mDefaultServiceInstance != null) {
188 | mDefaultServiceInstance.stopService();
189 | mDefaultServiceInstance = null;
190 | }
191 | try {
192 | Constructor extends BluetoothService> constructor =
193 | (Constructor extends BluetoothService>) mDefaultConfiguration.bluetoothServiceClass.getDeclaredConstructors()[0];
194 | constructor.setAccessible(true);
195 | BluetoothService bluetoothService = constructor.newInstance(mDefaultConfiguration);
196 | mDefaultServiceInstance = bluetoothService;
197 | } catch (InvocationTargetException e) {
198 | throw new RuntimeException(e);
199 | } catch (InstantiationException e) {
200 | throw new RuntimeException(e);
201 | } catch (IllegalAccessException e) {
202 | throw new RuntimeException(e);
203 | }
204 | }
205 |
206 | /**
207 | * Get the BluetoothService singleton instance.
208 | *
209 | * @return
210 | */
211 | public synchronized static BluetoothService getDefaultInstance() {
212 | if (mDefaultServiceInstance == null) {
213 | throw new IllegalStateException("BluetoothService is not initialized. Call BluetoothService.init(config).");
214 | }
215 | return mDefaultServiceInstance;
216 | }
217 |
218 | /* ====================================
219 | CALLBACKS
220 | ====================================== */
221 |
222 | public interface OnBluetoothEventCallback {
223 | void onDataRead(byte[] buffer, int length);
224 |
225 | void onStatusChange(BluetoothStatus status);
226 |
227 | void onDeviceName(String deviceName);
228 |
229 | void onToast(String message);
230 |
231 | void onDataWrite(byte[] buffer);
232 | }
233 |
234 | public interface OnBluetoothScanCallback {
235 | void onDeviceDiscovered(BluetoothDevice device, int rssi);
236 |
237 | void onStartScan();
238 |
239 | void onStopScan();
240 | }
241 | }
242 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | /**
28 | * Created by douglas on 25/11/14.
29 | */
30 | public enum BluetoothStatus {
31 | CONNECTED,
32 | CONNECTING,
33 | NONE
34 | }
35 |
--------------------------------------------------------------------------------
/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothclassiclibrary;
26 |
27 | public class BluetoothWriter {
28 | private final BluetoothService service;
29 |
30 | public BluetoothWriter(BluetoothService service) {
31 | this.service = service;
32 | }
33 |
34 | public void write(String msg) {
35 | if (service != null)
36 | service.write(msg.getBytes());
37 | }
38 |
39 | public void write(Integer number) {
40 | write(number.toString());
41 | }
42 |
43 | public void writeln(String msg) {
44 | write(msg + service.getConfiguration().characterDelimiter);
45 | }
46 |
47 | public void write(Character c){
48 | write(c.toString());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/BluetoothLowEnergyLibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion '25.0.0'
6 | defaultConfig {
7 | minSdkVersion 18
8 | targetSdkVersion 18
9 | versionCode 11
10 | versionName "0.3.5"
11 | }
12 | buildTypes {
13 | release {
14 | minifyEnabled false
15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 | }
17 | }
18 | compileOptions {
19 | sourceCompatibility JavaVersion.VERSION_1_7
20 | targetCompatibility JavaVersion.VERSION_1_7
21 | }
22 | productFlavors {
23 | }
24 | }
25 |
26 | dependencies {
27 | compile project(':BluetoothClassicLibrary')
28 | compile 'com.android.support:support-annotations:25.0.0'
29 | }
30 |
--------------------------------------------------------------------------------
/BluetoothLowEnergyLibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in C:/ferramentas/adt-bundle-windows-x86_64-20140702/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/BluetoothLowEnergyLibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BluetoothLowEnergyLibrary/src/main/java/com/github/douglasjunior/bluetoothlowenergylibrary/BluetoothLeService.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothlowenergylibrary;
26 |
27 | import android.Manifest;
28 | import android.bluetooth.BluetoothAdapter;
29 | import android.bluetooth.BluetoothDevice;
30 | import android.bluetooth.BluetoothGatt;
31 | import android.bluetooth.BluetoothGattCallback;
32 | import android.bluetooth.BluetoothGattCharacteristic;
33 | import android.bluetooth.BluetoothGattDescriptor;
34 | import android.bluetooth.BluetoothGattService;
35 | import android.bluetooth.BluetoothManager;
36 | import android.bluetooth.BluetoothProfile;
37 | import android.content.Context;
38 | import android.os.Build;
39 | import android.support.annotation.RequiresApi;
40 | import android.support.annotation.RequiresPermission;
41 | import android.util.Log;
42 |
43 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothConfiguration;
44 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
45 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus;
46 |
47 | import java.lang.reflect.Method;
48 | import java.nio.ByteBuffer;
49 | import java.nio.ByteOrder;
50 | import java.util.ArrayList;
51 | import java.util.Arrays;
52 | import java.util.List;
53 | import java.util.UUID;
54 |
55 |
56 | /**
57 | * Created by douglas on 16/03/15.
58 | */
59 | public class BluetoothLeService extends BluetoothService {
60 |
61 | private static final String TAG = BluetoothLeService.class.getSimpleName();
62 |
63 | private static final long SCAN_PERIOD = 10000;
64 |
65 | private final BluetoothAdapter btAdapter;
66 | private BluetoothGatt bluetoothGatt;
67 | private BluetoothGattCharacteristic characteristicRxTx;
68 |
69 | private final byte[] readBuffer;
70 | private int readBufferIndex = 0;
71 | private byte[][] writeBuffer;
72 | private int writeBufferIndex = 0;
73 |
74 | private int maxTransferBytes = 20;
75 |
76 | protected BluetoothLeService(BluetoothConfiguration config) {
77 | super(config);
78 | BluetoothManager btManager = (BluetoothManager) config.context.getSystemService(Context.BLUETOOTH_SERVICE);
79 | btAdapter = btManager.getAdapter();
80 | readBuffer = new byte[config.bufferSize];
81 | }
82 |
83 | private final BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {
84 |
85 | @Override
86 | public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
87 | super.onMtuChanged(gatt, mtu, status);
88 | Log.v(TAG, "onMtuChanged: " + mtu + " status: " + status);
89 | // Receive the requested MTU size.
90 | // See also https://stackoverflow.com/questions/24135682/android-sending-data-20-bytes-by-ble
91 | if (status == BluetoothGatt.GATT_SUCCESS) {
92 | // It discounts 3 bytes of metadata.
93 | maxTransferBytes = mtu - 3;
94 | }
95 | }
96 |
97 | @Override
98 | public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
99 | final byte[] data = characteristic.getValue();
100 | Log.v(TAG, "onCharacteristicChanged: " + new String(characteristic.getValue()));
101 | readData(data);
102 | super.onCharacteristicChanged(gatt, characteristic);
103 | }
104 |
105 | @Override
106 | public void onCharacteristicRead(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, int status) {
107 | super.onCharacteristicRead(gatt, characteristic, status);
108 | final byte[] data = characteristic.getValue();
109 | Log.v(TAG, "onCharacteristicRead: " + new String(data));
110 | if (BluetoothGatt.GATT_SUCCESS == status) {
111 | readData(data);
112 | } else {
113 | System.err.println("onCharacteristicRead error " + status);
114 | }
115 | }
116 |
117 | @Override
118 | public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
119 | super.onCharacteristicWrite(gatt, characteristic, status);
120 | final byte[] data = characteristic.getValue();
121 | //Log.v(TAG, "onCharacteristicWrite status: " + status + " data: " + new String(data));
122 | Log.v(TAG, "onCharacteristicWrite status: " + status + " data: " + data.length);
123 | if (BluetoothGatt.GATT_SUCCESS == status || status == 11) {
124 | if (onEventCallback != null)
125 | runOnMainThread(new Runnable() {
126 | @Override
127 | public void run() {
128 | onEventCallback.onDataWrite(data);
129 | }
130 | });
131 | writeCharacteristic();
132 | } else {
133 | System.err.println("onCharacteristicWrite error " + status);
134 | }
135 |
136 | }
137 |
138 | @RequiresPermission(Manifest.permission.BLUETOOTH)
139 | @Override
140 | public void onConnectionStateChange(final BluetoothGatt gatt, int status, final int newState) {
141 | super.onConnectionStateChange(gatt, status, newState);
142 | Log.v(TAG, "onConnectionStateChange: status: " + status + " newState: " + newState);
143 | if (status != BluetoothGatt.GATT_SUCCESS || newState == BluetoothProfile.STATE_DISCONNECTED) {
144 | gatt.close();
145 | if (mStatus == BluetoothStatus.NONE || mStatus == BluetoothStatus.CONNECTING)
146 | makeToast("Unable to connect to device");
147 | else if (mStatus == BluetoothStatus.CONNECTED)
148 | makeToast("Connection lost");
149 | updateState(BluetoothStatus.NONE);
150 | } else {
151 | if (newState == BluetoothProfile.STATE_CONNECTED) {
152 | //createBound(gatt.getDevice());
153 | gatt.discoverServices();
154 | } else if (newState == BluetoothProfile.STATE_CONNECTING) {
155 | updateState(BluetoothStatus.CONNECTING);
156 | }
157 | }
158 | }
159 |
160 | @Override
161 | public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
162 | Log.v(TAG, "onDescriptorRead");
163 | super.onDescriptorRead(gatt, descriptor, status);
164 | }
165 |
166 | @Override
167 | public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
168 | Log.v(TAG, "onDescriptorWrite");
169 | super.onDescriptorWrite(gatt, descriptor, status);
170 | }
171 |
172 | @Override
173 | public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
174 | Log.v(TAG, "onReadRemoteRssi");
175 | super.onReadRemoteRssi(gatt, rssi, status);
176 | }
177 |
178 | @Override
179 | public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
180 | Log.v(TAG, "onReliableWriteCompleted");
181 | super.onReliableWriteCompleted(gatt, status);
182 | }
183 |
184 | @RequiresPermission(Manifest.permission.BLUETOOTH)
185 | @Override
186 | public void onServicesDiscovered(BluetoothGatt gatt, int status) {
187 | super.onServicesDiscovered(gatt, status);
188 | Log.v(TAG, "onServicesDiscovered: " + status);
189 |
190 | if (BluetoothGatt.GATT_SUCCESS == status) {
191 | for (BluetoothGattService service : gatt.getServices()) {
192 | Log.v(TAG, "Service: " + service.getUuid());
193 | if (mConfig.uuidService == null || service.getUuid().equals(mConfig.uuidService)) {
194 | for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
195 | final int props = characteristic.getProperties();
196 | Log.v(TAG, "Characteristic: " + characteristic.getUuid() +
197 | " PROPERTY_WRITE: " + (props & BluetoothGattCharacteristic.PROPERTY_WRITE) +
198 | " PROPERTY_WRITE_NO_RESPONSE: " + (props & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE));
199 | if (characteristic.getUuid().equals(mConfig.uuidCharacteristic)) {
200 | characteristicRxTx = characteristic;
201 | gatt.setCharacteristicNotification(characteristic, true);
202 |
203 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
204 | // Request the MTU size to device.
205 | // See also https://stackoverflow.com/questions/24135682/android-sending-data-20-bytes-by-ble
206 | boolean requestMtu = bluetoothGatt.requestMtu(512);
207 | Log.v(TAG, "requestMtu: " + requestMtu);
208 |
209 | // Request a specific connection priority.
210 | // CONNECTION_PRIORITY_BALANCED is the default value if no connection parameter update is requested
211 | if (mConfig.connectionPriority != BluetoothGatt.CONNECTION_PRIORITY_BALANCED)
212 | requestConnectionPriority(mConfig.connectionPriority);
213 | }
214 |
215 | updateDeviceName(gatt.getDevice());
216 | updateState(BluetoothStatus.CONNECTED);
217 | return;
218 | }
219 | }
220 | }
221 | }
222 | Log.e(TAG, "Could not find uuidService:" + mConfig.uuidService + " and uuidCharacteristic:" + mConfig.uuidCharacteristic);
223 | } else {
224 | Log.e(TAG, "onServicesDiscovered error " + status);
225 | }
226 |
227 | // If arrived here, no service or characteristic has been found.
228 | gatt.disconnect();
229 | }
230 | };
231 |
232 | @RequiresPermission(Manifest.permission.BLUETOOTH)
233 | private void updateDeviceName(final BluetoothDevice device) {
234 | if (onEventCallback != null)
235 | runOnMainThread(new Runnable() {
236 | @RequiresPermission(Manifest.permission.BLUETOOTH)
237 | @Override
238 | public void run() {
239 | BluetoothDevice dev = device;
240 | if (dev.getName() == null)
241 | dev = btAdapter.getRemoteDevice(dev.getAddress());
242 | onEventCallback.onDeviceName(dev.getName());
243 | }
244 | });
245 | }
246 |
247 | // private void createBound(BluetoothDevice device) {
248 | // try {
249 | // if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
250 | // Method method = device.getClass().getMethod("createBond", (Class[]) null);
251 | // method.invoke(device, (Object[]) null);
252 | // }
253 | // } catch (Exception e) {
254 | // e.printStackTrace();
255 | // }
256 | // }
257 |
258 | private void readData(byte[] data) {
259 | final byte byteDelimiter = (byte) mConfig.characterDelimiter;
260 | for (byte temp : data) {
261 |
262 | if (temp == byteDelimiter) {
263 | if (readBufferIndex > 0) {
264 | dispatchBuffer(readBuffer, readBufferIndex);
265 | readBufferIndex = 0;
266 | }
267 | continue;
268 | }
269 | if (readBufferIndex == readBuffer.length - 1) {
270 | dispatchBuffer(readBuffer, readBufferIndex);
271 | readBufferIndex = 0;
272 | }
273 | readBuffer[readBufferIndex] = temp;
274 | readBufferIndex++;
275 |
276 | }
277 | }
278 |
279 | private void dispatchBuffer(byte[] buffer, int i) {
280 | final byte[] data = new byte[i];
281 | System.arraycopy(buffer, 0, data, 0, i);
282 | if (onEventCallback != null) {
283 | runOnMainThread(new Runnable() {
284 | @Override
285 | public void run() {
286 | onEventCallback.onDataRead(data, data.length);
287 | }
288 | });
289 | }
290 | }
291 |
292 | private void makeToast(final String message) {
293 | if (onEventCallback != null)
294 | runOnMainThread(new Runnable() {
295 | @Override
296 | public void run() {
297 | onEventCallback.onToast(message);
298 | }
299 | });
300 | }
301 |
302 | @RequiresPermission(Manifest.permission.BLUETOOTH)
303 | public void connect(BluetoothDevice bluetoothDevice) {
304 | if (btAdapter != null && btAdapter.isEnabled()) {
305 | if (bluetoothGatt != null) {
306 | bluetoothGatt.disconnect();
307 | }
308 |
309 | updateState(BluetoothStatus.CONNECTING);
310 |
311 | /*
312 | About this issue:
313 | https://code.google.com/p/android/issues/detail?id=92949
314 | http://stackoverflow.com/q/27633680/2826279
315 | */
316 |
317 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
318 | // If android verion is greather or equal to Android M (23), then call the connectGatt with TRANSPORT_LE.
319 | bluetoothGatt = bluetoothDevice.connectGatt(mConfig.context, false, btleGattCallback, mConfig.transport);
320 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
321 | // From Android LOLLIPOP (21) the transport types exists, but them are hide for use,
322 | // so is needed to use relfection to get the value
323 | try {
324 | Method connectGattMethod = bluetoothDevice.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
325 | connectGattMethod.setAccessible(true);
326 | bluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(bluetoothDevice, mConfig.context, false, btleGattCallback, mConfig.transport);
327 | } catch (Exception ex) {
328 | Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex);
329 | }
330 | }
331 |
332 | // If any try is fail, then call the connectGatt without transport
333 | if (bluetoothGatt == null) {
334 | bluetoothGatt = bluetoothDevice.connectGatt(mConfig.context, false, btleGattCallback);
335 | }
336 | }
337 | }
338 |
339 | @Override
340 | public void disconnect() {
341 | if (bluetoothGatt != null) {
342 | bluetoothGatt.disconnect();
343 | }
344 | }
345 |
346 | @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
347 | final Runnable mStopScanRunnable = new Runnable() {
348 | @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
349 | @Override
350 | public void run() {
351 | stopScan();
352 | }
353 | };
354 |
355 |
356 | final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
357 |
358 | @RequiresPermission(Manifest.permission.BLUETOOTH)
359 | @Override
360 | public void onLeScan(final BluetoothDevice device, final int rssi, byte[] scanRecord) {
361 | List uuids = parseUUIDs(scanRecord);
362 | Log.v(TAG, "onLeScan " + device.getName() + " " + new String(scanRecord) + " -> uuids: " + uuids);
363 | if (onScanCallback != null && (mConfig.uuid == null || uuids.contains(mConfig.uuid))) {
364 | runOnMainThread(new Runnable() {
365 | @Override
366 | public void run() {
367 | onScanCallback.onDeviceDiscovered(device, rssi);
368 | }
369 | });
370 | }
371 | }
372 |
373 | };
374 |
375 | @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
376 | @Override
377 | public void startScan() {
378 | if (onScanCallback != null)
379 | runOnMainThread(new Runnable() {
380 | @Override
381 | public void run() {
382 | onScanCallback.onStartScan();
383 | }
384 | });
385 |
386 | btAdapter.stopLeScan(mLeScanCallback);
387 |
388 | btAdapter.startLeScan(mLeScanCallback);
389 |
390 | runOnMainThread(mStopScanRunnable, SCAN_PERIOD);
391 | }
392 |
393 | private List parseUUIDs(final byte[] advertisedData) {
394 | List uuids = new ArrayList<>();
395 |
396 | int offset = 0;
397 | while (offset < (advertisedData.length - 2)) {
398 | int len = advertisedData[offset++];
399 | if (len == 0)
400 | break;
401 |
402 | int type = advertisedData[offset++];
403 | switch (type) {
404 | case 0x02: // Partial list of 16-bit UUIDs
405 | case 0x03: // Complete list of 16-bit UUIDs
406 | while (len > 1) {
407 | int uuid16 = advertisedData[offset++];
408 | uuid16 += (advertisedData[offset++] << 8);
409 | len -= 2;
410 | uuids.add(UUID.fromString(String.format("%08x-0000-1000-8000-00805f9b34fb", uuid16)));
411 | }
412 | break;
413 | case 0x06:// Partial list of 128-bit UUIDs
414 | case 0x07:// Complete list of 128-bit UUIDs
415 | // Loop through the advertised 128-bit UUID's.
416 | while (len >= 16) {
417 | try {
418 | // Wrap the advertised bits and order them.
419 | ByteBuffer buffer = ByteBuffer.wrap(advertisedData,
420 | offset++, 16).order(ByteOrder.LITTLE_ENDIAN);
421 | long mostSignificantBit = buffer.getLong();
422 | long leastSignificantBit = buffer.getLong();
423 | uuids.add(new UUID(leastSignificantBit,
424 | mostSignificantBit));
425 | } catch (IndexOutOfBoundsException e) {
426 | // Defensive programming.
427 | Log.e(TAG, e.toString());
428 | continue;
429 | } finally {
430 | // Move the offset to read the next uuid.
431 | offset += 15;
432 | len -= 16;
433 | }
434 | }
435 | break;
436 | default:
437 | offset += (len - 1);
438 | break;
439 | }
440 | }
441 |
442 | return uuids;
443 | }
444 |
445 | @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
446 | @Override
447 | public void stopScan() {
448 | removeRunnableFromHandler(mStopScanRunnable);
449 | btAdapter.stopLeScan(mLeScanCallback);
450 |
451 | if (onScanCallback != null)
452 | runOnMainThread(new Runnable() {
453 | @Override
454 | public void run() {
455 | onScanCallback.onStopScan();
456 | }
457 | });
458 | }
459 |
460 | public void stopService() {
461 | if (bluetoothGatt != null) {
462 | bluetoothGatt.disconnect();
463 | bluetoothGatt.close();
464 | }
465 | bluetoothGatt = null;
466 | }
467 |
468 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
469 | @Override
470 | public void requestConnectionPriority(int connectionPriority) {
471 | if (bluetoothGatt != null) {
472 | if (connectionPriority >= BluetoothGatt.CONNECTION_PRIORITY_BALANCED
473 | && connectionPriority <= BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER) {
474 | boolean requestConnectionPriority = bluetoothGatt.requestConnectionPriority(connectionPriority);
475 | Log.v(TAG, "requestConnectionPriority("+connectionPriority+"): " + requestConnectionPriority);
476 | } else
477 | Log.e(TAG, "requestConnectionPriority("+connectionPriority+"): ERROR - connectionPriority not within valid range");
478 | }
479 | }
480 |
481 | /**
482 | * Splits the bytes into packets according to the MTU size of the device, and writes the packets sequentially.
483 | *
484 | * See also https://stackoverflow.com/questions/24135682/android-sending-data-20-bytes-by-ble
485 | *
486 | * @param data
487 | */
488 | public void write(byte[] data) {
489 | Log.v(TAG, "write: " + data.length);
490 | if (bluetoothGatt != null && characteristicRxTx != null && mStatus == BluetoothStatus.CONNECTED) {
491 | if (data.length <= maxTransferBytes) {
492 | writeBufferIndex = 0;
493 | writeBuffer = new byte[1][data.length];
494 | writeBuffer[0] = data;
495 | } else {
496 | writeBufferIndex = 0;
497 | int bufferSize = (data.length / maxTransferBytes) + 1;
498 | writeBuffer = new byte[bufferSize][maxTransferBytes];
499 |
500 | for (int i = 0; i < writeBuffer.length; i++) {
501 | int start = i * maxTransferBytes;
502 | int end = start + maxTransferBytes;
503 | if (start >= data.length)
504 | break;
505 | if (end > data.length)
506 | end = data.length;
507 | writeBuffer[i] = Arrays.copyOfRange(data, start, end);
508 | }
509 | }
510 | writeCharacteristic();
511 | }
512 | }
513 |
514 | /**
515 | * Writes next packet to the Characteristic.
516 | *
517 | */
518 | private void writeCharacteristic() {
519 | Log.v(TAG, "writeCharacteristic " + writeBufferIndex);
520 | if (writeBufferIndex >= writeBuffer.length)
521 | return;
522 |
523 | byte[] bytes = writeBuffer[writeBufferIndex];
524 |
525 | boolean setValue = characteristicRxTx.setValue(bytes);
526 | Log.v(TAG, "setValue: " + setValue);
527 |
528 | boolean writeCharacteristic = bluetoothGatt.writeCharacteristic(characteristicRxTx);
529 | Log.v(TAG, "writeCharacteristic: " + writeCharacteristic);
530 |
531 | writeBufferIndex++;
532 | }
533 |
534 | }
535 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2015 Douglas Nassif Roma Junior
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AndroidBluetoothLibrary
2 |
3 | [](https://github.com/douglasjunior/AndroidBluetoothLibrary/blob/master/LICENSE)
4 | [](https://jitpack.io/#douglasjunior/AndroidBluetoothLibrary)
5 | [](#download)
6 | [](http://android-arsenal.com/details/1/5821)
7 |
8 | A Library for easy implementation of Serial Bluetooth Classic and Low Energy on Android. 💙
9 |
10 | - Bluetooth Classic working from Android 2.1 (API 7)
11 | - Bluetooth Low Energy working from Android 4.3 (API 18)
12 |
13 | ## Use
14 |
15 | ### Configuration
16 |
17 | #### Bluetooth Classic
18 | ```java
19 | BluetoothConfiguration config = new BluetoothConfiguration();
20 | config.context = getApplicationContext();
21 | config.bluetoothServiceClass = BluetoothClassicService.class;
22 | config.bufferSize = 1024;
23 | config.characterDelimiter = '\n';
24 | config.deviceName = "Your App Name";
25 | config.callListenersInMainThread = true;
26 |
27 | config.uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // Required
28 |
29 | BluetoothService.init(config);
30 | ```
31 |
32 | #### Bluetooth Low Energy
33 | ```java
34 | BluetoothConfiguration config = new BluetoothConfiguration();
35 | config.context = getApplicationContext();
36 | config.bluetoothServiceClass = BluetoothLeService.class;
37 | config.bufferSize = 1024;
38 | config.characterDelimiter = '\n';
39 | config.deviceName = "Your App Name";
40 | config.callListenersInMainThread = true;
41 |
42 | config.uuidService = UUID.fromString("e7810a71-73ae-499d-8c15-faa9aef0c3f2"); // Required
43 | config.uuidCharacteristic = UUID.fromString("bef8d6c9-9c21-4c9e-b632-bd58c1009f9f"); // Required
44 | config.transport = BluetoothDevice.TRANSPORT_LE; // Required for dual-mode devices
45 | config.uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // Used to filter found devices. Set null to find all devices.
46 |
47 | BluetoothService.init(config);
48 | ```
49 |
50 | ### Getting BluetoothService
51 |
52 | ```java
53 | BluetoothService service = BluetoothService.getDefaultInstance();
54 | ```
55 |
56 | ### Scanning
57 |
58 | ```java
59 | service.setOnScanCallback(new BluetoothService.OnBluetoothScanCallback() {
60 | @Override
61 | public void onDeviceDiscovered(BluetoothDevice device, int rssi) {
62 | }
63 |
64 | @Override
65 | public void onStartScan() {
66 | }
67 |
68 | @Override
69 | public void onStopScan() {
70 | }
71 | });
72 |
73 | service.startScan(); // See also service.stopScan();
74 | ```
75 |
76 | ### Connecting
77 |
78 | ```java
79 | service.setOnEventCallback(new BluetoothService.OnBluetoothEventCallback() {
80 | @Override
81 | public void onDataRead(byte[] buffer, int length) {
82 | }
83 |
84 | @Override
85 | public void onStatusChange(BluetoothStatus status) {
86 | }
87 |
88 | @Override
89 | public void onDeviceName(String deviceName) {
90 | }
91 |
92 | @Override
93 | public void onToast(String message) {
94 | }
95 |
96 | @Override
97 | public void onDataWrite(byte[] buffer) {
98 | }
99 | });
100 |
101 | service.connect(device); // See also service.disconnect();
102 | ```
103 |
104 | ### Writing
105 |
106 | ```java
107 | BluetoothWriter writer = new BluetoothWriter(service);
108 |
109 | writer.writeln("Your text here");
110 | ```
111 |
112 | ### Complete example
113 |
114 | See the [sample project](https://github.com/douglasjunior/AndroidBluetoothLibrary/tree/master/Sample/src/main/java/com/github/douglasjunior/bluetoothsample).
115 |
116 | ## Download
117 |
118 | 1. Add it in your root build.gradle at the end of repositories:
119 | ```javascript
120 | allprojects {
121 | repositories {
122 | ...
123 | maven { url "https://jitpack.io" }
124 | }
125 | }
126 | ```
127 |
128 | 2. Add the dependency
129 |
130 | 2.1. Bluetooth Classic
131 | ```javascript
132 | dependencies {
133 | implementation 'com.github.douglasjunior.AndroidBluetoothLibrary:BluetoothClassicLibrary:0.3.5'
134 | }
135 | ```
136 |
137 | 2.2. Bluetooth Low Energy
138 | ```javascript
139 | dependencies {
140 | implementation 'com.github.douglasjunior.AndroidBluetoothLibrary:BluetoothLowEnergyLibrary:0.3.5'
141 | }
142 | ```
143 |
144 | 3. Add permission in `AndroidManifest.xml`
145 |
146 | ```xml
147 |
148 |
149 |
150 |
151 |
152 | ...
153 |
154 | ```
155 |
156 | ## Known Issues / Troubleshooting
157 |
158 |
159 |
160 | - Scanning will not detect bluetooth devices if the user has denied Location Privacy Permission to your app. This library does not test for the permission and will not raise errors. (Android 6.0+) See: http://stackoverflow.com/a/33045489/2826279
161 |
162 | ## Contribute
163 |
164 | New features, bug fixes and improvements are welcome! For questions and suggestions use the [issues](https://github.com/douglasjunior/AndroidBluetoothLibrary/issues).
165 |
166 | Before submit your PR, run the gradle check.
167 | ```bash
168 | ./gradlew build connectedCheck
169 | ```
170 |
171 |
172 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=E32BUP77SVBA2)
173 |
174 | ## Licence
175 |
176 | ```
177 | The MIT License (MIT)
178 |
179 | Copyright (c) 2015 Douglas Nassif Roma Junior
180 | ```
181 |
182 | See the full [licence file](https://github.com/douglasjunior/AndroidBluetoothLibrary/blob/master/LICENSE).
183 |
184 |
--------------------------------------------------------------------------------
/Sample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion "26.0.3"
6 |
7 | defaultConfig {
8 | applicationId "com.github.douglasjunior.bluetoothsample"
9 | minSdkVersion 18
10 | targetSdkVersion 26
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 |
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 |
22 | }
23 |
24 | dependencies {
25 | compile fileTree(include: ['*.jar'], dir: 'libs')
26 | compile "com.android.support:appcompat-v7:$androidSupportVersion"
27 | compile "com.android.support:cardview-v7:$androidSupportVersion"
28 | compile "com.android.support:design:$androidSupportVersion"
29 | compile project(':BluetoothLowEnergyLibrary')
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/Sample/libs/print_lib_0.13.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/libs/print_lib_0.13.jar
--------------------------------------------------------------------------------
/Sample/libs/zxing.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/libs/zxing.jar
--------------------------------------------------------------------------------
/Sample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/douglas/ferramentas/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/Sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/BitmapActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.graphics.Bitmap;
28 | import android.graphics.BitmapFactory;
29 | import android.os.Bundle;
30 | import android.support.design.widget.FloatingActionButton;
31 | import android.support.v7.app.AppCompatActivity;
32 | import android.support.v7.widget.Toolbar;
33 | import android.view.View;
34 | import android.widget.ImageView;
35 |
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
37 | import com.wpx.util.WPXUtils;
38 |
39 | /**
40 | * Created by douglas on 26/05/17.
41 | */
42 |
43 | public class BitmapActivity extends AppCompatActivity implements View.OnClickListener {
44 |
45 | private FloatingActionButton mFab;
46 | private ImageView mImgOriginal;
47 | private ImageView mImgBlackWhite;
48 |
49 | private BluetoothService mService;
50 |
51 | private Bitmap imageBitmap;
52 |
53 | @Override
54 | protected void onCreate(Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 |
57 | setContentView(R.layout.activity_bitmap);
58 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
59 | setSupportActionBar(toolbar);
60 |
61 | mFab = (FloatingActionButton) findViewById(R.id.fab);
62 | mFab.setOnClickListener(this);
63 |
64 | mService = BluetoothService.getDefaultInstance();
65 |
66 | mImgOriginal = (ImageView) findViewById(R.id.img_original);
67 | mImgBlackWhite = (ImageView) findViewById(R.id.img_blackwhite);
68 |
69 | new Thread() {
70 | @Override
71 | public void run() {
72 | final Bitmap original = BitmapFactory.decodeResource(getResources(), R.drawable.bmw);
73 |
74 | final Bitmap resized = Bitmap.createScaledBitmap(original, 255, 255, false);
75 |
76 | final Bitmap editedBrightness = BitmapHelper.changeBitmapContrastBrightness(resized, 1, 50);
77 |
78 | resized.recycle();
79 |
80 | imageBitmap = editedBrightness;
81 |
82 | final Bitmap editedGray = BitmapHelper.changeBitmapBlackWhite(editedBrightness);
83 |
84 | runOnUiThread(new Runnable() {
85 | @Override
86 | public void run() {
87 | mImgOriginal.setImageBitmap(original);
88 | mImgBlackWhite.setImageBitmap(editedGray);
89 | }
90 | });
91 | }
92 | }.start();
93 | }
94 |
95 | @Override
96 | public void onClick(View v) {
97 | new Thread() {
98 | @Override
99 | public void run() {
100 | try {
101 | byte[] bytes = WPXUtils.decodeBitmap(imageBitmap);
102 | mService.write(bytes);
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | }
106 | }
107 | }.start();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/BitmapHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.graphics.Bitmap;
28 | import android.graphics.Canvas;
29 | import android.graphics.ColorMatrix;
30 | import android.graphics.ColorMatrixColorFilter;
31 | import android.graphics.Paint;
32 |
33 | /**
34 | * Created by douglas on 30/05/17.
35 | */
36 | public final class BitmapHelper {
37 |
38 | private BitmapHelper(){}
39 |
40 | /**
41 | * From https://stackoverflow.com/a/17887577/2826279
42 | *
43 | * @param bmp input bitmap
44 | * @param contrast 0..10 1 is default
45 | * @param brightness -255..255 0 is default
46 | * @return new bitmap
47 | */
48 | public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) {
49 | ColorMatrix cm = new ColorMatrix(new float[]
50 | {
51 | contrast, 0, 0, 0, brightness,
52 | 0, contrast, 0, 0, brightness,
53 | 0, 0, contrast, 0, brightness,
54 | 0, 0, 0, 1, 0
55 | });
56 | Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
57 |
58 | Canvas canvas = new Canvas(ret);
59 |
60 | Paint paint = new Paint();
61 | paint.setColorFilter(new ColorMatrixColorFilter(cm));
62 | canvas.drawBitmap(bmp, 0, 0, paint);
63 |
64 | return ret;
65 | }
66 |
67 | public static Bitmap changeBitmapBlackWhite(Bitmap bmp) {
68 | ColorMatrix cm = new ColorMatrix(new float[]
69 | {
70 | 1.5f, 1.5f, 1.5f, 0, 0,
71 | 1.5f, 1.5f, 1.5f, 0, 0,
72 | 1.5f, 1.5f, 1.5f, 0, 0,
73 | 0, 0, 0, 1, 0
74 | });
75 | cm.setSaturation(0);
76 | Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
77 |
78 | Canvas canvas = new Canvas(ret);
79 |
80 | Paint paint = new Paint();
81 | paint.setColorFilter(new ColorMatrixColorFilter(cm));
82 | canvas.drawBitmap(bmp, 0, 0, paint);
83 |
84 | return ret;
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/DeviceActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.os.Bundle;
28 | import android.support.design.widget.FloatingActionButton;
29 | import android.support.v7.app.AppCompatActivity;
30 | import android.support.v7.widget.Toolbar;
31 | import android.util.Log;
32 | import android.view.View;
33 | import android.widget.EditText;
34 |
35 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus;
37 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothWriter;
38 |
39 | /**
40 | * Created by douglas on 10/04/2017.
41 | */
42 |
43 | public class DeviceActivity extends AppCompatActivity implements BluetoothService.OnBluetoothEventCallback, View.OnClickListener {
44 |
45 | private static final String TAG = "DeviceActivity";
46 |
47 | private FloatingActionButton mFab;
48 | private EditText mEdRead;
49 | private EditText mEdWrite;
50 |
51 | private BluetoothService mService;
52 | private BluetoothWriter mWriter;
53 |
54 | @Override
55 | protected void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | setContentView(R.layout.activity_device);
58 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
59 | setSupportActionBar(toolbar);
60 |
61 | mFab = (FloatingActionButton) findViewById(R.id.fab);
62 | mFab.setOnClickListener(this);
63 |
64 | mEdRead = (EditText) findViewById(R.id.ed_read);
65 | mEdWrite = (EditText) findViewById(R.id.ed_write);
66 |
67 | mService = BluetoothService.getDefaultInstance();
68 | mWriter = new BluetoothWriter(mService);
69 | }
70 |
71 | @Override
72 | protected void onResume() {
73 | super.onResume();
74 | mService.setOnEventCallback(this);
75 | }
76 |
77 | @Override
78 | public void onDataRead(byte[] buffer, int length) {
79 | Log.d(TAG, "onDataRead: " + new String(buffer, 0, length));
80 | mEdRead.append("< " + new String(buffer, 0, length) + "\n");
81 | }
82 |
83 | @Override
84 | protected void onDestroy() {
85 | super.onDestroy();
86 | mService.disconnect();
87 | }
88 |
89 | @Override
90 | public void onStatusChange(BluetoothStatus status) {
91 | Log.d(TAG, "onStatusChange: " + status);
92 | }
93 |
94 | @Override
95 | public void onDeviceName(String deviceName) {
96 | Log.d(TAG, "onDeviceName: " + deviceName);
97 | }
98 |
99 | @Override
100 | public void onToast(String message) {
101 | Log.d(TAG, "onToast");
102 | }
103 |
104 | @Override
105 | public void onDataWrite(byte[] buffer) {
106 | Log.d(TAG, "onDataWrite");
107 | mEdRead.append("> " + new String(buffer));
108 | }
109 |
110 | @Override
111 | public void onClick(View v) {
112 | mWriter.writeln(mEdWrite.getText().toString());
113 | mEdWrite.setText("");
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/DeviceItemAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.bluetooth.BluetoothDevice;
28 | import android.content.Context;
29 | import android.support.v7.widget.RecyclerView;
30 | import android.text.TextUtils;
31 | import android.view.LayoutInflater;
32 | import android.view.View;
33 | import android.view.ViewGroup;
34 | import android.widget.TextView;
35 |
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothDeviceDecorator;
37 |
38 | import java.util.ArrayList;
39 | import java.util.Collection;
40 | import java.util.List;
41 | import java.util.Set;
42 |
43 | /**
44 | * Created by douglas on 10/04/2017.
45 | */
46 |
47 | public class DeviceItemAdapter extends RecyclerView.Adapter {
48 |
49 | private final Context mContext;
50 | private final List mDevices;
51 | private final LayoutInflater mInflater;
52 | private OnAdapterItemClickListener mOnItemClickListener;
53 |
54 |
55 | public DeviceItemAdapter(Context context, List devices) {
56 | super();
57 | mContext = context;
58 | mDevices = decorateDevices(devices);
59 | mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
60 | }
61 |
62 | public static List decorateDevices(Collection btDevices) {
63 | List devices = new ArrayList<>();
64 | for (BluetoothDevice dev : btDevices) {
65 | devices.add(new BluetoothDeviceDecorator(dev, 0));
66 | }
67 | return devices;
68 | }
69 |
70 | public DeviceItemAdapter(Context context, Set devices) {
71 | this(context, new ArrayList<>(devices));
72 | }
73 |
74 | @Override
75 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
76 | ViewHolder vh = new ViewHolder(mInflater.inflate(R.layout.device_item, parent, false));
77 | return vh;
78 | }
79 |
80 | @Override
81 | public void onBindViewHolder(ViewHolder holder, final int position) {
82 | final BluetoothDeviceDecorator device = mDevices.get(position);
83 |
84 | holder.tvName.setText(TextUtils.isEmpty(device.getName()) ? "---" : device.getName());
85 | holder.tvAddress.setText(device.getAddress());
86 | holder.tvRSSI.setText(device.getRSSI() + "");
87 |
88 | holder.itemView.setOnClickListener(new View.OnClickListener() {
89 | @Override
90 | public void onClick(View v) {
91 | mOnItemClickListener.onItemClick(device, position);
92 | }
93 | });
94 | }
95 |
96 | @Override
97 | public int getItemCount() {
98 | return mDevices.size();
99 | }
100 |
101 | public List getDevices() {
102 | return mDevices;
103 | }
104 |
105 | public void setOnAdapterItemClickListener(OnAdapterItemClickListener onItemClickListener) {
106 | mOnItemClickListener = onItemClickListener;
107 | }
108 |
109 | public interface OnAdapterItemClickListener {
110 | public void onItemClick(BluetoothDeviceDecorator device, int position);
111 | }
112 |
113 | public static class ViewHolder extends RecyclerView.ViewHolder {
114 |
115 | private final TextView tvName;
116 | private final TextView tvAddress;
117 | private final TextView tvRSSI;
118 |
119 | public ViewHolder(View itemView) {
120 | super(itemView);
121 | tvName = (TextView) itemView.findViewById(R.id.tv_name);
122 | tvAddress = (TextView) itemView.findViewById(R.id.tv_address);
123 | tvRSSI = (TextView) itemView.findViewById(R.id.tv_rssi);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/EscPosHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.graphics.Bitmap;
28 |
29 | import java.io.ByteArrayOutputStream;
30 | import java.io.IOException;
31 |
32 | /**
33 | * Code adapted from http://new-grumpy-mentat.blogspot.com.br/2014/06/java-escpos-image-printing.html
34 | */
35 | public final class EscPosHelper {
36 |
37 | private EscPosHelper() {
38 | }
39 |
40 | private final static char ESC_CHAR = 0x1B;
41 | private final static byte[] FEED_LINE = {10};
42 | private final static byte[] SELECT_BIT_IMAGE_MODE = {ESC_CHAR, 0x2A, 33};
43 | private final static byte[] SET_LINE_SPACE_24 = new byte[]{ESC_CHAR, 0x33, 24};
44 | private final static byte[] SET_LINE_SPACE_30 = new byte[]{ESC_CHAR, 0x33, 30};
45 |
46 | /**
47 | * Send image to the printer to be printed.
48 | *
49 | * @param image 2D Array of RGB colors (Row major order)
50 | */
51 | public static byte[] printImage(Bitmap image) throws IOException {
52 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
53 |
54 | baos.write(SET_LINE_SPACE_24);
55 | for (int y = 0; y < image.getHeight(); y += 24) {
56 | baos.write(SELECT_BIT_IMAGE_MODE);// bit mode
57 | baos.write(new byte[]{(byte) (0x00ff & image.getWidth()), (byte) ((0xff00 & image.getWidth()) >> 8)});// width, low & high
58 | for (int x = 0; x < image.getWidth(); x++) {
59 | // For each vertical line/slice must collect 3 bytes (24 bytes)
60 | baos.write(collectSlice(y, x, image));
61 | }
62 |
63 | baos.write(FEED_LINE);
64 | }
65 | baos.write(SET_LINE_SPACE_30);
66 |
67 | return baos.toByteArray();
68 | }
69 |
70 | /**
71 | * Defines if a color should be printed (burned).
72 | *
73 | * @param color RGB color.
74 | * @return true if should be printed/burned (black), false otherwise (white).
75 | */
76 | private static boolean shouldPrintColor(int color) {
77 | final int threshold = 127;
78 | int a, r, g, b, luminance;
79 | a = (color >> 24) & 0xff;
80 | if (a != 0xff) { // ignore pixels with alpha channel
81 | return false;
82 | }
83 | r = (color >> 16) & 0xff;
84 | g = (color >> 8) & 0xff;
85 | b = color & 0xff;
86 |
87 | luminance = (int) (0.299 * r + 0.587 * g + 0.114 * b);
88 |
89 | return luminance < threshold;
90 | }
91 |
92 | /**
93 | * Collect a slice of 3 bytes with 24 dots for image printing.
94 | *
95 | * @param y row position of the pixel.
96 | * @param x column position of the pixel.
97 | * @param image 2D array of pixels of the image (RGB, row major order).
98 | * @return 3 byte array with 24 dots (field set).
99 | */
100 | private static byte[] collectSlice(int y, int x, Bitmap image) {
101 | byte[] slices = new byte[]{0, 0, 0};
102 | for (int yy = y, i = 0; yy < y + 24 && i < 3; yy += 8, i++) {// va a hacer 3 ciclos
103 | byte slice = 0;
104 | for (int b = 0; b < 8; b++) {
105 | int yyy = yy + b;
106 | if (yyy >= image.getHeight()) {
107 | continue;
108 | }
109 | int color = image.getPixel(x, yyy);
110 | boolean v = shouldPrintColor(color);
111 | slice |= (byte) ((v ? 1 : 0) << (7 - b));
112 | }
113 | slices[i] = slice;
114 | }
115 |
116 | return slices;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.bluetooth.BluetoothAdapter;
28 | import android.bluetooth.BluetoothDevice;
29 | import android.content.DialogInterface;
30 | import android.content.Intent;
31 | import android.os.Bundle;
32 | import android.support.v7.app.AlertDialog;
33 | import android.support.v7.app.AppCompatActivity;
34 | import android.support.v7.widget.LinearLayoutManager;
35 | import android.support.v7.widget.RecyclerView;
36 | import android.support.v7.widget.Toolbar;
37 | import android.util.Log;
38 | import android.view.Menu;
39 | import android.view.MenuItem;
40 | import android.view.View;
41 | import android.widget.ProgressBar;
42 | import android.widget.Toast;
43 |
44 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothDeviceDecorator;
45 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
46 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus;
47 |
48 | import java.util.Arrays;
49 |
50 | public class MainActivity extends AppCompatActivity implements BluetoothService.OnBluetoothScanCallback, BluetoothService.OnBluetoothEventCallback, DeviceItemAdapter.OnAdapterItemClickListener {
51 |
52 | public static final String TAG = "BluetoothExample";
53 |
54 | private ProgressBar pgBar;
55 | private Menu mMenu;
56 | private RecyclerView mRecyclerView;
57 | private DeviceItemAdapter mAdapter;
58 |
59 | private BluetoothAdapter mBluetoothAdapter;
60 | private BluetoothService mService;
61 | private boolean mScanning;
62 |
63 | @Override
64 | protected void onCreate(Bundle savedInstanceState) {
65 | super.onCreate(savedInstanceState);
66 | setContentView(R.layout.activity_main);
67 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
68 | setSupportActionBar(toolbar);
69 |
70 | pgBar = (ProgressBar) findViewById(R.id.pg_bar);
71 | pgBar.setVisibility(View.GONE);
72 |
73 | mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
74 |
75 | mRecyclerView = (RecyclerView) findViewById(R.id.rv);
76 | LinearLayoutManager lm = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
77 | mRecyclerView.setLayoutManager(lm);
78 |
79 | mAdapter = new DeviceItemAdapter(this, mBluetoothAdapter.getBondedDevices());
80 | mAdapter.setOnAdapterItemClickListener(this);
81 | mRecyclerView.setAdapter(mAdapter);
82 |
83 | mService = BluetoothService.getDefaultInstance();
84 |
85 | mService.setOnScanCallback(this);
86 | mService.setOnEventCallback(this);
87 | }
88 |
89 | @Override
90 | protected void onResume() {
91 | super.onResume();
92 | mService.setOnEventCallback(this);
93 | }
94 |
95 | @Override
96 | public boolean onCreateOptionsMenu(Menu menu) {
97 | getMenuInflater().inflate(R.menu.menu_main, menu);
98 | mMenu = menu;
99 | return true;
100 | }
101 |
102 | @Override
103 | public boolean onOptionsItemSelected(MenuItem item) {
104 | int id = item.getItemId();
105 |
106 | if (id == R.id.action_scan) {
107 | startStopScan();
108 | return true;
109 | }
110 |
111 | return super.onOptionsItemSelected(item);
112 | }
113 |
114 | private void startStopScan() {
115 | if (!mScanning) {
116 | mService.startScan();
117 | } else {
118 | mService.stopScan();
119 | }
120 | }
121 |
122 | @Override
123 | public void onDeviceDiscovered(BluetoothDevice device, int rssi) {
124 | Log.d(TAG, "onDeviceDiscovered: " + device.getName() + " - " + device.getAddress() + " - " + Arrays.toString(device.getUuids()));
125 | BluetoothDeviceDecorator dv = new BluetoothDeviceDecorator(device, rssi);
126 | int index = mAdapter.getDevices().indexOf(dv);
127 | if (index < 0) {
128 | mAdapter.getDevices().add(dv);
129 | mAdapter.notifyItemInserted(mAdapter.getDevices().size() - 1);
130 | } else {
131 | mAdapter.getDevices().get(index).setDevice(device);
132 | mAdapter.getDevices().get(index).setRSSI(rssi);
133 | mAdapter.notifyItemChanged(index);
134 | }
135 | }
136 |
137 | @Override
138 | public void onStartScan() {
139 | Log.d(TAG, "onStartScan");
140 | mScanning = true;
141 | pgBar.setVisibility(View.VISIBLE);
142 | mMenu.findItem(R.id.action_scan).setTitle(R.string.action_stop);
143 | }
144 |
145 | @Override
146 | public void onStopScan() {
147 | Log.d(TAG, "onStopScan");
148 | mScanning = false;
149 | pgBar.setVisibility(View.GONE);
150 | mMenu.findItem(R.id.action_scan).setTitle(R.string.action_scan);
151 | }
152 |
153 | @Override
154 | public void onDataRead(byte[] buffer, int length) {
155 | Log.d(TAG, "onDataRead");
156 | }
157 |
158 | @Override
159 | public void onStatusChange(BluetoothStatus status) {
160 | Log.d(TAG, "onStatusChange: " + status);
161 | Toast.makeText(this, status.toString(), Toast.LENGTH_SHORT).show();
162 |
163 | if (status == BluetoothStatus.CONNECTED) {
164 | CharSequence colors[] = new CharSequence[]{"Try text", "Try picture"};
165 |
166 | AlertDialog.Builder builder = new AlertDialog.Builder(this);
167 | builder.setTitle("Select");
168 | builder.setItems(colors, new DialogInterface.OnClickListener() {
169 | @Override
170 | public void onClick(DialogInterface dialog, int which) {
171 | if (which == 0) {
172 | startActivity(new Intent(MainActivity.this, DeviceActivity.class));
173 | } else {
174 | startActivity(new Intent(MainActivity.this, BitmapActivity.class));
175 | }
176 | }
177 | });
178 | builder.setCancelable(false);
179 | builder.show();
180 | }
181 |
182 | }
183 |
184 | @Override
185 | public void onDeviceName(String deviceName) {
186 | Log.d(TAG, "onDeviceName: " + deviceName);
187 | }
188 |
189 | @Override
190 | public void onToast(String message) {
191 | Log.d(TAG, "onToast");
192 | }
193 |
194 | @Override
195 | public void onDataWrite(byte[] buffer) {
196 | Log.d(TAG, "onDataWrite");
197 | }
198 |
199 | @Override
200 | public void onItemClick(BluetoothDeviceDecorator device, int position) {
201 | mService.connect(device.getDevice());
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/Sample/src/main/java/com/github/douglasjunior/bluetoothsample/SampleApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsample;
26 |
27 | import android.app.Application;
28 | import android.bluetooth.BluetoothDevice;
29 | import android.bluetooth.BluetoothGatt;
30 |
31 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothClassicService;
32 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothConfiguration;
33 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
34 |
35 | import java.util.UUID;
36 |
37 | /**
38 | * Created by douglas on 29/05/17.
39 | */
40 | public class SampleApplication extends Application {
41 |
42 | /*
43 | * Change for the UUID that you want.
44 | */
45 | private static final UUID UUID_DEVICE = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
46 | private static final UUID UUID_SERVICE = UUID.fromString("e7810a71-73ae-499d-8c15-faa9aef0c3f2");
47 | private static final UUID UUID_CHARACTERISTIC = UUID.fromString("bef8d6c9-9c21-4c9e-b632-bd58c1009f9f");
48 |
49 | @Override
50 | public void onCreate() {
51 | super.onCreate();
52 |
53 | BluetoothConfiguration config = new BluetoothConfiguration();
54 |
55 | config.bluetoothServiceClass = BluetoothClassicService.class; // BluetoothClassicService.class or BluetoothLeService.class
56 |
57 | config.context = getApplicationContext();
58 | config.bufferSize = 1024;
59 | config.characterDelimiter = '\n';
60 | config.deviceName = "Bluetooth Sample";
61 | config.callListenersInMainThread = true;
62 |
63 | //config.uuid = null; // When using BluetoothLeService.class set null to show all devices on scan.
64 | config.uuid = UUID_DEVICE; // For Classic
65 |
66 | config.uuidService = UUID_SERVICE; // For BLE
67 | config.uuidCharacteristic = UUID_CHARACTERISTIC; // For BLE
68 | config.transport = BluetoothDevice.TRANSPORT_LE; // Only for dual-mode devices
69 |
70 | // For BLE
71 | config.connectionPriority = BluetoothGatt.CONNECTION_PRIORITY_HIGH; // Automatically request connection priority just after connection is through.
72 | //or request connection priority manually, mService.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
73 |
74 | BluetoothService.init(config);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/bmw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/drawable/bmw.jpg
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/jac.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/drawable/jac.JPG
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/drawable/loading.jpg
--------------------------------------------------------------------------------
/Sample/src/main/res/drawable/palio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/drawable/palio.jpg
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_bitmap.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
37 |
38 |
44 |
45 |
51 |
52 |
53 |
54 |
61 |
62 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_device.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
37 |
38 |
39 |
43 |
44 |
53 |
54 |
58 |
59 |
66 |
67 |
68 |
75 |
76 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
31 |
32 |
33 |
34 |
35 |
36 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Sample/src/main/res/layout/device_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
27 |
28 |
35 |
36 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Sample/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/Sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Sample/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Bluetooth Sample
3 | SCAN
4 | STOP
5 | Device
6 |
7 |
--------------------------------------------------------------------------------
/Sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/SampleKotlin/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/SampleKotlin/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 26
7 | buildToolsVersion "26.0.3"
8 |
9 | defaultConfig {
10 | applicationId "com.github.douglasjunior.bluetoothsamplekotlin"
11 | minSdkVersion 18
12 | targetSdkVersion 22
13 | versionCode 1
14 | versionName "1.0"
15 | }
16 |
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 |
24 | }
25 |
26 | dependencies {
27 | compile fileTree(include: ['*.jar'], dir: 'libs')
28 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
29 | compile "com.android.support:appcompat-v7:$androidSupportVersion"
30 | compile "com.android.support:cardview-v7:$androidSupportVersion"
31 | compile "com.android.support:design:$androidSupportVersion"
32 | compile project(':BluetoothLowEnergyLibrary')
33 | }
34 |
--------------------------------------------------------------------------------
/SampleKotlin/libs/print_lib_0.13.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/libs/print_lib_0.13.jar
--------------------------------------------------------------------------------
/SampleKotlin/libs/zxing.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/libs/zxing.jar
--------------------------------------------------------------------------------
/SampleKotlin/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/BitmapActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin;
26 |
27 | import android.graphics.Bitmap;
28 | import android.graphics.BitmapFactory;
29 | import android.os.Bundle;
30 | import android.support.design.widget.FloatingActionButton;
31 | import android.support.v7.app.AppCompatActivity;
32 | import android.support.v7.widget.Toolbar;
33 | import android.view.View;
34 | import android.widget.ImageView;
35 |
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
37 | import com.wpx.util.WPXUtils;
38 |
39 | /**
40 | * Created by douglas on 26/05/17.
41 | */
42 |
43 | public class BitmapActivity extends AppCompatActivity implements View.OnClickListener {
44 |
45 | private FloatingActionButton mFab;
46 | private ImageView mImgOriginal;
47 | private ImageView mImgBlackWhite;
48 |
49 | private BluetoothService mService;
50 |
51 | private Bitmap imageBitmap;
52 |
53 | @Override
54 | protected void onCreate(Bundle savedInstanceState) {
55 | super.onCreate(savedInstanceState);
56 |
57 | setContentView(R.layout.activity_bitmap);
58 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
59 | setSupportActionBar(toolbar);
60 |
61 | mFab = (FloatingActionButton) findViewById(R.id.fab);
62 | mFab.setOnClickListener(this);
63 |
64 | mService = BluetoothService.getDefaultInstance();
65 |
66 | mImgOriginal = (ImageView) findViewById(R.id.img_original);
67 | mImgBlackWhite = (ImageView) findViewById(R.id.img_blackwhite);
68 |
69 | new Thread() {
70 | @Override
71 | public void run() {
72 | final Bitmap original = BitmapFactory.decodeResource(getResources(), R.drawable.bmw);
73 |
74 | final Bitmap resized = Bitmap.createScaledBitmap(original, 255, 255, false);
75 |
76 | final Bitmap editedBrightness = BitmapHelper.changeBitmapContrastBrightness(resized, 1, 50);
77 |
78 | resized.recycle();
79 |
80 | imageBitmap = editedBrightness;
81 |
82 | final Bitmap editedGray = BitmapHelper.changeBitmapBlackWhite(editedBrightness);
83 |
84 | runOnUiThread(new Runnable() {
85 | @Override
86 | public void run() {
87 | mImgOriginal.setImageBitmap(original);
88 | mImgBlackWhite.setImageBitmap(editedGray);
89 | }
90 | });
91 | }
92 | }.start();
93 | }
94 |
95 | @Override
96 | public void onClick(View v) {
97 | new Thread() {
98 | @Override
99 | public void run() {
100 | try {
101 | byte[] bytes = WPXUtils.decodeBitmap(imageBitmap);
102 | mService.write(bytes);
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | }
106 | }
107 | }.start();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/BitmapHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin;
26 |
27 | import android.graphics.Bitmap;
28 | import android.graphics.Canvas;
29 | import android.graphics.ColorMatrix;
30 | import android.graphics.ColorMatrixColorFilter;
31 | import android.graphics.Paint;
32 |
33 | /**
34 | * Created by douglas on 30/05/17.
35 | */
36 | public final class BitmapHelper {
37 |
38 | private BitmapHelper(){}
39 |
40 | /**
41 | * From https://stackoverflow.com/a/17887577/2826279
42 | *
43 | * @param bmp input bitmap
44 | * @param contrast 0..10 1 is default
45 | * @param brightness -255..255 0 is default
46 | * @return new bitmap
47 | */
48 | public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) {
49 | ColorMatrix cm = new ColorMatrix(new float[]
50 | {
51 | contrast, 0, 0, 0, brightness,
52 | 0, contrast, 0, 0, brightness,
53 | 0, 0, contrast, 0, brightness,
54 | 0, 0, 0, 1, 0
55 | });
56 | Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
57 |
58 | Canvas canvas = new Canvas(ret);
59 |
60 | Paint paint = new Paint();
61 | paint.setColorFilter(new ColorMatrixColorFilter(cm));
62 | canvas.drawBitmap(bmp, 0, 0, paint);
63 |
64 | return ret;
65 | }
66 |
67 | public static Bitmap changeBitmapBlackWhite(Bitmap bmp) {
68 | ColorMatrix cm = new ColorMatrix(new float[]
69 | {
70 | 1.5f, 1.5f, 1.5f, 0, 0,
71 | 1.5f, 1.5f, 1.5f, 0, 0,
72 | 1.5f, 1.5f, 1.5f, 0, 0,
73 | 0, 0, 0, 1, 0
74 | });
75 | cm.setSaturation(0);
76 | Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
77 |
78 | Canvas canvas = new Canvas(ret);
79 |
80 | Paint paint = new Paint();
81 | paint.setColorFilter(new ColorMatrixColorFilter(cm));
82 | canvas.drawBitmap(bmp, 0, 0, paint);
83 |
84 | return ret;
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/DeviceActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin;
26 |
27 | import android.os.Bundle;
28 | import android.support.design.widget.FloatingActionButton;
29 | import android.support.v7.app.AppCompatActivity;
30 | import android.support.v7.widget.Toolbar;
31 | import android.util.Log;
32 | import android.view.View;
33 | import android.widget.EditText;
34 |
35 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService;
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus;
37 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothWriter;
38 |
39 | /**
40 | * Created by douglas on 10/04/2017.
41 | */
42 |
43 | public class DeviceActivity extends AppCompatActivity implements BluetoothService.OnBluetoothEventCallback, View.OnClickListener {
44 |
45 | private static final String TAG = "DeviceActivity";
46 |
47 | private FloatingActionButton mFab;
48 | private EditText mEdRead;
49 | private EditText mEdWrite;
50 |
51 | private BluetoothService mService;
52 | private BluetoothWriter mWriter;
53 |
54 | @Override
55 | protected void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 | setContentView(R.layout.activity_device);
58 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
59 | setSupportActionBar(toolbar);
60 |
61 | mFab = (FloatingActionButton) findViewById(R.id.fab);
62 | mFab.setOnClickListener(this);
63 |
64 | mEdRead = (EditText) findViewById(R.id.ed_read);
65 | mEdWrite = (EditText) findViewById(R.id.ed_write);
66 |
67 | mService = BluetoothService.getDefaultInstance();
68 | mWriter = new BluetoothWriter(mService);
69 | }
70 |
71 | @Override
72 | protected void onResume() {
73 | super.onResume();
74 | mService.setOnEventCallback(this);
75 | }
76 |
77 | @Override
78 | public void onDataRead(byte[] buffer, int length) {
79 | Log.d(TAG, "onDataRead: " + new String(buffer, 0, length));
80 | mEdRead.append("< " + new String(buffer, 0, length) + "\n");
81 | }
82 |
83 | @Override
84 | protected void onDestroy() {
85 | super.onDestroy();
86 | mService.disconnect();
87 | }
88 |
89 | @Override
90 | public void onStatusChange(BluetoothStatus status) {
91 | Log.d(TAG, "onStatusChange: " + status);
92 | }
93 |
94 | @Override
95 | public void onDeviceName(String deviceName) {
96 | Log.d(TAG, "onDeviceName: " + deviceName);
97 | }
98 |
99 | @Override
100 | public void onToast(String message) {
101 | Log.d(TAG, "onToast");
102 | }
103 |
104 | @Override
105 | public void onDataWrite(byte[] buffer) {
106 | Log.d(TAG, "onDataWrite");
107 | mEdRead.append("> " + new String(buffer));
108 | }
109 |
110 | @Override
111 | public void onClick(View v) {
112 | mWriter.writeln(mEdWrite.getText().toString());
113 | mEdWrite.setText("");
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/DeviceItemAdapter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin;
26 |
27 | import android.bluetooth.BluetoothDevice;
28 | import android.content.Context;
29 | import android.support.v7.widget.RecyclerView;
30 | import android.text.TextUtils;
31 | import android.view.LayoutInflater;
32 | import android.view.View;
33 | import android.view.ViewGroup;
34 | import android.widget.TextView;
35 |
36 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothDeviceDecorator;
37 |
38 | import java.util.ArrayList;
39 | import java.util.Collection;
40 | import java.util.List;
41 | import java.util.Set;
42 |
43 | /**
44 | * Created by douglas on 10/04/2017.
45 | */
46 |
47 | public class DeviceItemAdapter extends RecyclerView.Adapter {
48 |
49 | private final Context mContext;
50 | private final List mDevices;
51 | private final LayoutInflater mInflater;
52 | private OnAdapterItemClickListener mOnItemClickListener;
53 |
54 |
55 | public DeviceItemAdapter(Context context, List devices) {
56 | super();
57 | mContext = context;
58 | mDevices = decorateDevices(devices);
59 | mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
60 | }
61 |
62 | public static List decorateDevices(Collection btDevices) {
63 | List devices = new ArrayList<>();
64 | for (BluetoothDevice dev : btDevices) {
65 | devices.add(new BluetoothDeviceDecorator(dev, 0));
66 | }
67 | return devices;
68 | }
69 |
70 | public DeviceItemAdapter(Context context, Set devices) {
71 | this(context, new ArrayList<>(devices));
72 | }
73 |
74 | @Override
75 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
76 | ViewHolder vh = new ViewHolder(mInflater.inflate(R.layout.device_item, parent, false));
77 | return vh;
78 | }
79 |
80 | @Override
81 | public void onBindViewHolder(ViewHolder holder, final int position) {
82 | final BluetoothDeviceDecorator device = mDevices.get(position);
83 |
84 | holder.tvName.setText(TextUtils.isEmpty(device.getName()) ? "---" : device.getName());
85 | holder.tvAddress.setText(device.getAddress());
86 | holder.tvRSSI.setText(device.getRSSI() + "");
87 |
88 | holder.itemView.setOnClickListener(new View.OnClickListener() {
89 | @Override
90 | public void onClick(View v) {
91 | mOnItemClickListener.onItemClick(device, position);
92 | }
93 | });
94 | }
95 |
96 | @Override
97 | public int getItemCount() {
98 | return mDevices.size();
99 | }
100 |
101 | public List getDevices() {
102 | return mDevices;
103 | }
104 |
105 | public void setOnAdapterItemClickListener(OnAdapterItemClickListener onItemClickListener) {
106 | mOnItemClickListener = onItemClickListener;
107 | }
108 |
109 | public interface OnAdapterItemClickListener {
110 | public void onItemClick(BluetoothDeviceDecorator device, int position);
111 | }
112 |
113 | public static class ViewHolder extends RecyclerView.ViewHolder {
114 |
115 | private final TextView tvName;
116 | private final TextView tvAddress;
117 | private final TextView tvRSSI;
118 |
119 | public ViewHolder(View itemView) {
120 | super(itemView);
121 | tvName = (TextView) itemView.findViewById(R.id.tv_name);
122 | tvAddress = (TextView) itemView.findViewById(R.id.tv_address);
123 | tvRSSI = (TextView) itemView.findViewById(R.id.tv_rssi);
124 | }
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/EscPosHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin;
26 |
27 | import android.graphics.Bitmap;
28 |
29 | import java.io.ByteArrayOutputStream;
30 | import java.io.IOException;
31 |
32 | /**
33 | * Code adapted from http://new-grumpy-mentat.blogspot.com.br/2014/06/java-escpos-image-printing.html
34 | */
35 | public final class EscPosHelper {
36 |
37 | private EscPosHelper() {
38 | }
39 |
40 | private final static char ESC_CHAR = 0x1B;
41 | private final static byte[] FEED_LINE = {10};
42 | private final static byte[] SELECT_BIT_IMAGE_MODE = {ESC_CHAR, 0x2A, 33};
43 | private final static byte[] SET_LINE_SPACE_24 = new byte[]{ESC_CHAR, 0x33, 24};
44 | private final static byte[] SET_LINE_SPACE_30 = new byte[]{ESC_CHAR, 0x33, 30};
45 |
46 | /**
47 | * Send image to the printer to be printed.
48 | *
49 | * @param image 2D Array of RGB colors (Row major order)
50 | */
51 | public static byte[] printImage(Bitmap image) throws IOException {
52 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
53 |
54 | baos.write(SET_LINE_SPACE_24);
55 | for (int y = 0; y < image.getHeight(); y += 24) {
56 | baos.write(SELECT_BIT_IMAGE_MODE);// bit mode
57 | baos.write(new byte[]{(byte) (0x00ff & image.getWidth()), (byte) ((0xff00 & image.getWidth()) >> 8)});// width, low & high
58 | for (int x = 0; x < image.getWidth(); x++) {
59 | // For each vertical line/slice must collect 3 bytes (24 bytes)
60 | baos.write(collectSlice(y, x, image));
61 | }
62 |
63 | baos.write(FEED_LINE);
64 | }
65 | baos.write(SET_LINE_SPACE_30);
66 |
67 | return baos.toByteArray();
68 | }
69 |
70 | /**
71 | * Defines if a color should be printed (burned).
72 | *
73 | * @param color RGB color.
74 | * @return true if should be printed/burned (black), false otherwise (white).
75 | */
76 | private static boolean shouldPrintColor(int color) {
77 | final int threshold = 127;
78 | int a, r, g, b, luminance;
79 | a = (color >> 24) & 0xff;
80 | if (a != 0xff) { // ignore pixels with alpha channel
81 | return false;
82 | }
83 | r = (color >> 16) & 0xff;
84 | g = (color >> 8) & 0xff;
85 | b = color & 0xff;
86 |
87 | luminance = (int) (0.299 * r + 0.587 * g + 0.114 * b);
88 |
89 | return luminance < threshold;
90 | }
91 |
92 | /**
93 | * Collect a slice of 3 bytes with 24 dots for image printing.
94 | *
95 | * @param y row position of the pixel.
96 | * @param x column position of the pixel.
97 | * @param image 2D array of pixels of the image (RGB, row major order).
98 | * @return 3 byte array with 24 dots (field set).
99 | */
100 | private static byte[] collectSlice(int y, int x, Bitmap image) {
101 | byte[] slices = new byte[]{0, 0, 0};
102 | for (int yy = y, i = 0; yy < y + 24 && i < 3; yy += 8, i++) {// va a hacer 3 ciclos
103 | byte slice = 0;
104 | for (int b = 0; b < 8; b++) {
105 | int yyy = yy + b;
106 | if (yyy >= image.getHeight()) {
107 | continue;
108 | }
109 | int color = image.getPixel(x, yyy);
110 | boolean v = shouldPrintColor(color);
111 | slice |= (byte) ((v ? 1 : 0) << (7 - b));
112 | }
113 | slices[i] = slice;
114 | }
115 |
116 | return slices;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/MainActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin
26 |
27 | import android.bluetooth.BluetoothAdapter
28 | import android.bluetooth.BluetoothDevice
29 | import android.content.DialogInterface
30 | import android.content.Intent
31 | import android.os.Bundle
32 | import android.support.v7.app.AlertDialog
33 | import android.support.v7.app.AppCompatActivity
34 | import android.support.v7.widget.LinearLayoutManager
35 | import android.support.v7.widget.RecyclerView
36 | import android.support.v7.widget.Toolbar
37 | import android.util.Log
38 | import android.view.Menu
39 | import android.view.MenuItem
40 | import android.view.View
41 | import android.widget.ProgressBar
42 | import android.widget.Toast
43 |
44 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothDeviceDecorator
45 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService
46 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus
47 |
48 | import java.util.Arrays
49 |
50 | class MainActivity : AppCompatActivity(), BluetoothService.OnBluetoothScanCallback, BluetoothService.OnBluetoothEventCallback, DeviceItemAdapter.OnAdapterItemClickListener {
51 |
52 | private var pgBar: ProgressBar? = null
53 | private var mMenu: Menu? = null
54 | private var mRecyclerView: RecyclerView? = null
55 | private var mAdapter: DeviceItemAdapter? = null
56 |
57 | private var mBluetoothAdapter: BluetoothAdapter? = null
58 | private var mService: BluetoothService? = null
59 | private var mScanning: Boolean = false
60 |
61 | override fun onCreate(savedInstanceState: Bundle?) {
62 | super.onCreate(savedInstanceState)
63 | setContentView(R.layout.activity_main)
64 | val toolbar = findViewById(R.id.toolbar) as Toolbar
65 | setSupportActionBar(toolbar)
66 |
67 | pgBar = findViewById(R.id.pg_bar) as ProgressBar
68 | pgBar!!.visibility = View.GONE
69 |
70 | mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
71 |
72 | mRecyclerView = findViewById(R.id.rv) as RecyclerView
73 | val lm = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
74 | mRecyclerView!!.layoutManager = lm
75 |
76 | mAdapter = DeviceItemAdapter(this, mBluetoothAdapter!!.bondedDevices)
77 | mAdapter!!.setOnAdapterItemClickListener(this)
78 | mRecyclerView!!.adapter = mAdapter
79 |
80 | mService = BluetoothService.getDefaultInstance()
81 |
82 | mService!!.setOnScanCallback(this)
83 | mService!!.setOnEventCallback(this)
84 | }
85 |
86 | override fun onResume() {
87 | super.onResume()
88 | mService!!.setOnEventCallback(this)
89 | }
90 |
91 | override fun onCreateOptionsMenu(menu: Menu): Boolean {
92 | menuInflater.inflate(R.menu.menu_main, menu)
93 | mMenu = menu
94 | return true
95 | }
96 |
97 | override fun onOptionsItemSelected(item: MenuItem): Boolean {
98 | val id = item.itemId
99 |
100 | if (id == R.id.action_scan) {
101 | startStopScan()
102 | return true
103 | }
104 |
105 | return super.onOptionsItemSelected(item)
106 | }
107 |
108 | private fun startStopScan() {
109 | if (!mScanning) {
110 | mService!!.startScan()
111 | } else {
112 | mService!!.stopScan()
113 | }
114 | }
115 |
116 | override fun onDeviceDiscovered(device: BluetoothDevice, rssi: Int) {
117 | Log.d(TAG, "onDeviceDiscovered: " + device.name + " - " + device.address + " - " + Arrays.toString(device.uuids))
118 | val dv = BluetoothDeviceDecorator(device, rssi)
119 | val index = mAdapter!!.devices.indexOf(dv)
120 | if (index < 0) {
121 | mAdapter!!.devices.add(dv)
122 | mAdapter!!.notifyItemInserted(mAdapter!!.devices.size - 1)
123 | } else {
124 | mAdapter!!.devices[index].device = device
125 | mAdapter!!.devices[index].rssi = rssi
126 | mAdapter!!.notifyItemChanged(index)
127 | }
128 | }
129 |
130 | override fun onStartScan() {
131 | Log.d(TAG, "onStartScan")
132 | mScanning = true
133 | pgBar!!.visibility = View.VISIBLE
134 | mMenu!!.findItem(R.id.action_scan).setTitle(R.string.action_stop)
135 | }
136 |
137 | override fun onStopScan() {
138 | Log.d(TAG, "onStopScan")
139 | mScanning = false
140 | pgBar!!.visibility = View.GONE
141 | mMenu!!.findItem(R.id.action_scan).setTitle(R.string.action_scan)
142 | }
143 |
144 | override fun onDataRead(buffer: ByteArray, length: Int) {
145 | Log.d(TAG, "onDataRead")
146 | }
147 |
148 | override fun onStatusChange(status: BluetoothStatus) {
149 | Log.d(TAG, "onStatusChange: $status")
150 | Toast.makeText(this, status.toString(), Toast.LENGTH_SHORT).show()
151 |
152 | if (status == BluetoothStatus.CONNECTED) {
153 | val colors = arrayOf("Try text", "Try picture")
154 |
155 | val builder = AlertDialog.Builder(this)
156 | builder.setTitle("Select")
157 | builder.setItems(colors) { dialog, which ->
158 | if (which == 0) {
159 | startActivity(Intent(this@MainActivity, DeviceActivity::class.java))
160 | } else {
161 | startActivity(Intent(this@MainActivity, BitmapActivity::class.java))
162 | }
163 | }
164 | builder.setCancelable(false)
165 | builder.show()
166 | }
167 |
168 | }
169 |
170 | override fun onDeviceName(deviceName: String) {
171 | Log.d(TAG, "onDeviceName: $deviceName")
172 | }
173 |
174 | override fun onToast(message: String) {
175 | Log.d(TAG, "onToast")
176 | }
177 |
178 | override fun onDataWrite(buffer: ByteArray) {
179 | Log.d(TAG, "onDataWrite")
180 | }
181 |
182 | override fun onItemClick(device: BluetoothDeviceDecorator, position: Int) {
183 | mService!!.connect(device.device)
184 | }
185 |
186 | companion object {
187 |
188 | val TAG = "BluetoothExampleKotlin"
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/java/com/github/douglasjunior/bluetoothsamplekotlin/SampleApplication.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * MIT License
3 | *
4 | * Copyright (c) 2015 Douglas Nassif Roma Junior
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 |
25 | package com.github.douglasjunior.bluetoothsamplekotlin
26 |
27 | import android.app.Application
28 | import android.bluetooth.BluetoothDevice
29 | import android.bluetooth.BluetoothGatt
30 |
31 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothClassicService
32 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothConfiguration
33 | import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService
34 |
35 | import java.util.UUID
36 |
37 | /**
38 | * Created by douglas on 29/05/17.
39 | */
40 | class SampleApplication : Application() {
41 |
42 | override fun onCreate() {
43 | super.onCreate()
44 |
45 | val config = BluetoothConfiguration()
46 |
47 | config.bluetoothServiceClass = BluetoothClassicService::class.java // BluetoothClassicService.class or BluetoothLeService.class
48 |
49 | config.context = applicationContext
50 | config.bufferSize = 1024
51 | config.characterDelimiter = '\n'
52 | config.deviceName = "Bluetooth Sample"
53 | config.callListenersInMainThread = true
54 |
55 | //config.uuid = null; // When using BluetoothLeService.class set null to show all devices on scan.
56 | config.uuid = UUID_DEVICE // For Classic
57 |
58 | config.uuidService = UUID_SERVICE // For BLE
59 | config.uuidCharacteristic = UUID_CHARACTERISTIC // For BLE
60 | config.transport = BluetoothDevice.TRANSPORT_LE // Only for dual-mode devices
61 |
62 | // For BLE
63 | config.connectionPriority = BluetoothGatt.CONNECTION_PRIORITY_HIGH // Automatically request connection priority just after connection is through.
64 | //or request connection priority manually, mService.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
65 |
66 | BluetoothService.init(config)
67 | }
68 |
69 | companion object {
70 |
71 | /*
72 | * Change for the UUID that you want.
73 | */
74 | private val UUID_DEVICE = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")
75 | private val UUID_SERVICE = UUID.fromString("e7810a71-73ae-499d-8c15-faa9aef0c3f2")
76 | private val UUID_CHARACTERISTIC = UUID.fromString("bef8d6c9-9c21-4c9e-b632-bd58c1009f9f")
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable/bmw.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/drawable/bmw.jpg
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable/jac.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/drawable/jac.JPG
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/drawable/loading.jpg
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/drawable/palio.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/drawable/palio.jpg
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/layout/activity_bitmap.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
37 |
38 |
44 |
45 |
51 |
52 |
53 |
54 |
61 |
62 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/layout/activity_device.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
32 |
33 |
37 |
38 |
39 |
43 |
44 |
53 |
54 |
58 |
59 |
66 |
67 |
68 |
75 |
76 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
23 |
24 |
31 |
32 |
33 |
34 |
35 |
36 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/layout/device_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
22 |
23 |
27 |
28 |
35 |
36 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/SampleKotlin/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Bluetooth Sample Kotlin
3 | SCAN
4 | STOP
5 | Device
6 |
7 |
--------------------------------------------------------------------------------
/SampleKotlin/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | kotlin_version = '1.2.61'
6 | androidSupportVersion = '26.1.0'
7 | }
8 |
9 | repositories {
10 | jcenter()
11 | maven {
12 | url 'https://maven.google.com/'
13 | name 'Google'
14 | }
15 | maven { url 'https://jitpack.io' }
16 | }
17 | dependencies {
18 | classpath 'com.android.tools.build:gradle:2.3.1'
19 |
20 | // NOTE: Do not place your application dependencies here; they belong
21 | // in the individual module build.gradle files
22 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }
23 | }
24 |
25 | allprojects {
26 | repositories {
27 | jcenter()
28 | maven {
29 | url 'https://maven.google.com/'
30 | name 'Google'
31 | }
32 | maven { url 'https://jitpack.io' }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/douglasjunior/AndroidBluetoothLibrary/65180766464f3ba702b4825fa9cfef13c4083308/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Apr 08 16:18:50 BRT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':BluetoothLowEnergyLibrary', ':BluetoothClassicLibrary', ':Sample', ':SampleKotlin'
2 |
--------------------------------------------------------------------------------