├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.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-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ └── main.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── news
│ │ │ └── example
│ │ │ └── zdw
│ │ │ └── bluedemo
│ │ │ └── MainActivity.java
│ ├── test
│ │ └── java
│ │ │ └── news
│ │ │ └── example
│ │ │ └── zdw
│ │ │ └── bluedemo
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── news
│ │ └── example
│ │ └── zdw
│ │ └── bluedemo
│ │ └── ApplicationTest.java
├── build.gradle
└── proguard-rules.pro
├── blelib
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── cn
│ │ │ └── me
│ │ │ └── com
│ │ │ └── blelib
│ │ │ └── ble
│ │ │ ├── bluetooth
│ │ │ ├── IBlueToothMessageCallBack.java
│ │ │ ├── BleConfig.java
│ │ │ └── BlueToothMessageListener.java
│ │ │ └── utils
│ │ │ ├── ULog.java
│ │ │ ├── DensityUtil.java
│ │ │ └── Utils.java
│ ├── test
│ │ └── java
│ │ │ └── cn
│ │ │ └── me
│ │ │ └── com
│ │ │ └── blelib
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── cn
│ │ └── me
│ │ └── com
│ │ └── blelib
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ ├── gradle-wrapper.properties
│ └── gradle-wrapper.properties.bak
├── .gitignore
├── .idea
├── vcs.xml
├── modules.xml
└── runConfigurations.xml
├── gradle.properties
├── gradlew.bat
├── README.md
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/blelib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':blelib'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BlueDemo
3 |
4 |
--------------------------------------------------------------------------------
/blelib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | BleLib
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tangchao5206/BleUtils/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
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-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties.bak:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
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-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/test/java/news/example/zdw/bluedemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package news.example.zdw.bluedemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/news/example/zdw/bluedemo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package news.example.zdw.bluedemo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/blelib/src/test/java/cn/me/com/blelib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/blelib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.1"
6 |
7 | defaultConfig {
8 | applicationId "news.example.zdw.bluedemo"
9 | minSdkVersion 21
10 | targetSdkVersion 22
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | testCompile 'junit:junit:4.12'
25 | compile project(':blelib')
26 | }
27 |
--------------------------------------------------------------------------------
/app/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:\AndroidSDK/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 |
--------------------------------------------------------------------------------
/blelib/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:\androidsdk/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/bluetooth/IBlueToothMessageCallBack.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.bluetooth;
2 |
3 | /**
4 | * 创 建 人: tangchao
5 | * 创建日期: 2016/6/30 14:40
6 | * 修改时间:
7 | * 修改备注:
8 | */
9 | public interface IBlueToothMessageCallBack {
10 |
11 |
12 |
13 | /**
14 | * 断开连接
15 | * @return
16 | */
17 | void onDisConnected();
18 |
19 | //蓝牙设备连接成功
20 | void onConnected();
21 |
22 | void onConnectFail();
23 | /**
24 | * 写入数据
25 | * @param bs
26 | */
27 | void writeData(byte[] bs);
28 |
29 |
30 |
31 |
32 | void onServicesDiscovered();
33 |
34 | void onDescriptorWriteSuccess();
35 |
36 |
37 | void onDescriptorWrite();
38 |
39 |
40 | void onCharacteristicRead(String data);
41 | /**
42 | * 接收到数据
43 | */
44 | void onReceiveMessage(String data);
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/blelib/src/androidTest/java/cn/me/com/blelib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("cn.me.com.blelib.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
17 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/blelib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.1"
6 |
7 | defaultConfig {
8 | minSdkVersion 21
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(dir: 'libs', include: ['*.jar'])
26 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
27 | exclude group: 'com.android.support', module: 'support-annotations'
28 | })
29 | compile 'com.android.support:appcompat-v7:25.3.1'
30 | testCompile 'junit:junit:4.12'
31 | }
32 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/utils/ULog.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.utils;
2 |
3 | import android.content.Context;
4 | import android.util.Log;
5 | import android.widget.Toast;
6 |
7 | /**
8 | * 创 建 人: tangchao
9 | * 创建日期: 2016/6/30 14:44
10 | * 修改时间:
11 | * 修改备注:
12 | */
13 | public class ULog {
14 |
15 | /** 正式上线是设为false */
16 | private static boolean testMode = true;
17 |
18 | public static void v(String tag, String msg) {
19 | if (testMode) {
20 | Log.v(tag, msg);
21 | }
22 | }
23 |
24 | public static void d(String tag, String msg) {
25 | if (testMode) {
26 | Log.d(tag, msg);
27 | }
28 | }
29 |
30 | public static void i(String tag, String msg) {
31 | if (testMode) {
32 | Log.i(tag, msg);
33 | }
34 |
35 | }
36 |
37 | public static void w(String tag, String msg) {
38 | if (testMode) {
39 | Log.w(tag, msg);
40 | }
41 | }
42 |
43 | public static void e(String tag, String msg) {
44 | if (testMode) {
45 | Log.e(tag, msg);
46 | }
47 | }
48 |
49 | public static void showToast(Context context, String str) {
50 | if (str != null) {
51 |
52 | Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/utils/DensityUtil.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.utils;
2 |
3 | import android.content.Context;
4 | import android.view.Display;
5 | import android.view.WindowManager;
6 |
7 | /**
8 | * 创 建 人: tangchao
9 | * 创建日期: 2016/6/30 14:43
10 | * 修改时间:
11 | * 修改备注:
12 | */
13 | public class DensityUtil {
14 |
15 | @SuppressWarnings("deprecation")
16 | public static int getScreenHeight(Context activity) {
17 | WindowManager manager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
18 | Display display = manager.getDefaultDisplay();
19 | return display.getHeight();
20 | }
21 |
22 | @SuppressWarnings("deprecation")
23 | public static int getScreenWidth(Context activity) {
24 | WindowManager manager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
25 | Display display = manager.getDefaultDisplay();
26 | return display.getWidth();
27 | }
28 |
29 | public static int dip2px(Context context, float dpValue) {
30 | final float scale = context.getResources().getDisplayMetrics().density;
31 | return (int) (dpValue * scale + 0.5f);
32 | }
33 |
34 | public static int px2dip(Context context, float pxValue) {
35 | final float scale = context.getResources().getDisplayMetrics().density;
36 | return (int) (pxValue / scale + 0.5f);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/bluetooth/BleConfig.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.bluetooth;
2 |
3 | /**
4 | * 创 建 人: tangchao
5 | * 创建日期: 2016/6/30 14:38
6 | * 修改时间:
7 | * 修改备注:
8 | */
9 | public abstract class BleConfig {
10 |
11 | //初始化监听消息返回结果
12 | public static final int START_DEVICE_SUCCESS = 1;
13 | public static final int START_DEVICE_UNSUPPORTBLE = -1;
14 | public static final int START_DEVICE_UNSUPPORTBT = -2;
15 | public static final int START_DEVICE_VERSON = -3;
16 | public static final int START_DEVICE_ERROR = -4;
17 |
18 | //
19 | public final static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
20 |
21 | /* *//**
22 | * 根据设备名称查询设备类型
23 | * @param deviceName
24 | * @return
25 | *//*
26 | public static int getDeviceTypeByDeviceName(String deviceName) {
27 | String[] deviceNames = {
28 | DEVICENAMETAGS_TIZHONGCHENG,
29 | DEVICENAMETAGS_XUEYANGYI
30 |
31 | };
32 | if (deviceName!=null){
33 | deviceName = deviceName.toLowerCase();
34 | for(int i = 0; i < deviceNames.length; i++) {
35 | if(deviceNames[i].toLowerCase().indexOf(deviceName) > -1) {
36 | return i;
37 | }
38 | }
39 | }
40 | return -1;
41 | }
42 | */
43 |
44 | /**
45 | * 返回设备通知uuid
46 | * @param deviceType
47 | * @return
48 | */
49 | public abstract String[] getNotifyUUIDsByDeviceType(int deviceType);
50 |
51 | /**
52 | * 返回设备数据写入uuid
53 | * @param deviceType
54 | * @return
55 | */
56 | public abstract String getWriteUUIDByDeviceType(int deviceType) ;
57 |
58 |
59 | /**
60 | * 返回设备service uuid
61 | * @param deviceType
62 | * @return
63 | */
64 | public abstract String getDeviceServiceUUID(int deviceType) ;
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BleUtils
2 | 安卓低功耗蓝牙ble快速上手
3 |
4 | 最近项目中用到蓝牙ble的需求,于是把蓝牙代码整合起来,方便调用。
5 | 第一次传代码到github,不足之处,希望大家多支持支持
6 |
7 |
8 | 功能特点:
9 |
10 | 1.简洁明了,蓝牙业务与ui充分解耦
11 |
12 |
13 | 项目会一直维护,发现问题欢迎提出~ 会第一时间修复哟~ qq:852234130 希望用得着的朋友点个start,你们的支持才是我继续下去的动力,在此先谢过~
14 | 蓝牙操作主要封装在blelib中, BlueToothMessageListener为主要蓝牙相关操作处理类,通过IBlueToothMessageCallBack回调数据。
15 |
16 |
17 | #3.代码中如何使用
18 |
19 | 1.蓝牙操作类初始化:
20 | btMsgListener = BlueToothMessageListener.create(this).setCallback(btMsgCallBack)
21 | .setServiceUUid(DEVICE_SERVICE_UUID) //必须要
22 | .setNotifyUUid(NOTIFY_CHARACTERISTICSUUID)//必须要
23 | .setReadUUid(READ_CHARACTERISTICSUUID)
24 | .setWriteUUid(WRITE_CHARACTERISTICSUUID)
25 | .setBleName(DEVICE_NAME_SPO2) //蓝牙名称和mac地址二选一
26 | .setBleMac(DEVICE_MAC_SPO2);
27 |
28 | 2. //检测手机能否支持蓝牙ble,支持就开始
29 |
30 | int respose = btMsgListener.checkBle();
31 | if (respose>0){
32 | ULog.showToast(this,"蓝牙初始化成功");
33 | btMsgListener.startListener(true); //true 代表通过蓝牙名字搜索蓝牙,false代表通过mac地址搜索蓝牙
34 |
35 | }else if (respose==-1){
36 | ULog.showToast(this,"当前手机不支持蓝牙ble");
37 |
38 | }else if (respose==-2){
39 | ULog.showToast(this,"当前手机不支持蓝牙");
40 |
41 | }else if (respose==-3){
42 | ULog.showToast(this,"安卓系统版本必须大于4.3");
43 | }
44 |
45 |
46 |
47 |
48 | 3.数据回调
49 |
50 |
51 | IBlueToothMessageCallBack btMsgCallBack = new IBlueToothMessageCallBack() {
52 |
53 | //蓝牙断开连接
54 | @Override
55 | public void onDisConnected() {
56 |
57 | }
58 |
59 |
60 | //蓝牙连接成功
61 | @Override
62 | public void onConnected() {
63 |
64 | }
65 | //蓝牙连接失败
66 | @Override
67 | public void onConnectFail() {
68 |
69 | }
70 |
71 | //蓝牙写入数据
72 | @Override
73 | public void writeData(byte[] bs) {
74 |
75 | btMsgListener.writeLlsAlertLevel(bs);
76 |
77 | }
78 | //发现服务
79 | @Override
80 | public void onServicesDiscovered() {
81 |
82 | }
83 | //通知uuid全部通知完毕后回调
84 | @Override
85 | public void onDescriptorWriteSuccess() {
86 | final byte[] datas = {(byte)0xaa, (byte)0x55, (byte)0x04, (byte)0xb1, 0x00, 0x00, (byte)0xb5};
87 | btMsgListener.writeLlsAlertLevel(datas);
88 | }
89 |
90 | @Override
91 | public void onDescriptorWrite() {
92 |
93 | }
94 | //读特征值
95 | @Override
96 | public void onCharacteristicRead(String data) {
97 |
98 | }
99 | //接收到的数据
100 | @Override
101 | public void onReceiveMessage(final String data) {
102 | ULog.d(TAG,"receive data "+data);
103 | runOnUiThread(new Runnable() {
104 | @Override
105 | public void run() {
106 | text.setText(data);
107 | }
108 | });
109 | }
110 |
111 |
112 | };
113 |
--------------------------------------------------------------------------------
/app/src/main/java/news/example/zdw/bluedemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package news.example.zdw.bluedemo;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Message;
7 | import android.widget.TextView;
8 |
9 | import cn.me.com.blelib.ble.bluetooth.BlueToothMessageListener;
10 | import cn.me.com.blelib.ble.bluetooth.IBlueToothMessageCallBack;
11 | import cn.me.com.blelib.ble.utils.ULog;
12 |
13 | public class MainActivity extends Activity {
14 |
15 | private static final String TAG = "MainActivity";
16 |
17 | private BlueToothMessageListener btMsgListener;
18 |
19 | private TextView text;
20 |
21 | private Handler mHanlder;
22 |
23 |
24 | //设备标识((按上面设备类型顺序填写))
25 | public final static String DEVICE_NAME_SPO2 = "iChoice"; //血氧蓝牙设备名称uuid
26 |
27 | //设备mac地址
28 | public final static String DEVICE_MAC_SPO2 = "08:7C:BE:2F:87:BA"; //血氧蓝牙mac地址
29 |
30 |
31 |
32 | //设备Service uuid
33 | public final static String DEVICE_SERVICE_UUID = "ba11f08c-5f14-0b0d-1080-007cbe2f87ba"; //血氧服务id
34 |
35 | //设备通知uuid //血氧通知uuid(一般设备是一个,这里有四个,看协议决定)
36 | public final static String[] NOTIFY_CHARACTERISTICSUUID = {
37 |
38 | "0000cd01-0000-1000-8000-00805f9b34fb",
39 | "0000cd02-0000-1000-8000-00805f9b34fb",
40 | "0000cd03-0000-1000-8000-00805f9b34fb",
41 | "0000cd04-0000-1000-8000-00805f9b34fb"
42 | };
43 |
44 |
45 | //设备写数据uuid (按上面设备类型顺序填写)
46 | public final static String WRITE_CHARACTERISTICSUUID = "0000cd20-0000-1000-8000-00805f9b34fb"; //血氧写uuid
47 |
48 | public final static String READ_CHARACTERISTICSUUID = "0000cd21-0000-1000-8000-00805f9b34fb"; //血氧读uuid
49 |
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | setContentView(R.layout.main);
55 | text = (TextView) findViewById(R.id.txt);
56 | btMsgListener = BlueToothMessageListener.create(this).setCallback(btMsgCallBack)
57 | .setServiceUUid(DEVICE_SERVICE_UUID) //必须要
58 | .setNotifyUUid(NOTIFY_CHARACTERISTICSUUID)//必须要
59 | .setReadUUid(READ_CHARACTERISTICSUUID)
60 | .setWriteUUid(WRITE_CHARACTERISTICSUUID)
61 | .setBleName(DEVICE_NAME_SPO2) //蓝牙名称和mac地址二选一
62 | .setBleMac(DEVICE_MAC_SPO2);
63 |
64 | //检测手机能否支持蓝牙ble
65 | int respose = btMsgListener.checkBle();
66 | if (respose>0){
67 | ULog.showToast(this,"蓝牙初始化成功");
68 | btMsgListener.startListener(true); //true 代表通过蓝牙名字搜索蓝牙,false代表通过mac地址搜索蓝牙
69 |
70 | }else if (respose==-1){
71 | ULog.showToast(this,"当前手机不支持蓝牙ble");
72 |
73 | }else if (respose==-2){
74 | ULog.showToast(this,"当前手机不支持蓝牙");
75 |
76 | }else if (respose==-3){
77 | ULog.showToast(this,"安卓系统版本必须大于4.3");
78 | }
79 |
80 | mHanlder = new Handler() {
81 | @Override
82 | public void dispatchMessage(Message msg) {
83 | super.dispatchMessage(msg);
84 | text.setText(msg.obj.toString());
85 | }
86 | };
87 | }
88 |
89 |
90 | @Override
91 | protected void onDestroy() {
92 |
93 | super.onDestroy();
94 | if (btMsgListener!=null){
95 | btMsgListener.stopListenerMessage();
96 | btMsgListener=null;
97 | }
98 |
99 |
100 | }
101 |
102 |
103 | /**
104 | *回调
105 | */
106 | IBlueToothMessageCallBack btMsgCallBack = new IBlueToothMessageCallBack() {
107 |
108 |
109 |
110 |
111 | //蓝牙断开连接
112 | @Override
113 | public void onDisConnected() {
114 |
115 | }
116 |
117 |
118 | //蓝牙连接成功
119 | @Override
120 | public void onConnected() {
121 |
122 | }
123 | //蓝牙连接失败
124 | @Override
125 | public void onConnectFail() {
126 |
127 | }
128 |
129 | //蓝牙写入数据
130 | @Override
131 | public void writeData(byte[] bs) {
132 |
133 | btMsgListener.writeLlsAlertLevel(bs);
134 |
135 | }
136 |
137 | @Override
138 | public void onServicesDiscovered() {
139 |
140 | }
141 | //通知uuid全部通知完毕后回调
142 | @Override
143 | public void onDescriptorWriteSuccess() {
144 | final byte[] datas = {(byte)0xaa, (byte)0x55, (byte)0x04, (byte)0xb1, 0x00, 0x00, (byte)0xb5};
145 | btMsgListener.writeLlsAlertLevel(datas);
146 | }
147 |
148 | @Override
149 | public void onDescriptorWrite() {
150 |
151 | }
152 | //读特征值
153 | @Override
154 | public void onCharacteristicRead(String data) {
155 |
156 | }
157 | //接收到的数据
158 | @Override
159 | public void onReceiveMessage(final String data) {
160 | ULog.d(TAG,"receive data "+data);
161 | runOnUiThread(new Runnable() {
162 | @Override
163 | public void run() {
164 | text.setText(data);
165 | }
166 | });
167 | }
168 |
169 |
170 | };
171 | }
172 |
--------------------------------------------------------------------------------
/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 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/utils/Utils.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.utils;
2 |
3 | import android.content.ContentResolver;
4 | import android.content.Context;
5 | import android.content.pm.PackageInfo;
6 | import android.content.pm.PackageManager;
7 | import android.database.Cursor;
8 | import android.graphics.Bitmap;
9 | import android.graphics.BitmapFactory;
10 | import android.media.ThumbnailUtils;
11 | import android.net.DhcpInfo;
12 | import android.net.TrafficStats;
13 | import android.net.Uri;
14 | import android.net.wifi.WifiManager;
15 | import android.provider.MediaStore;
16 | import android.text.format.Formatter;
17 |
18 | import java.io.File;
19 | import java.io.FileInputStream;
20 | import java.io.FileNotFoundException;
21 | import java.io.IOException;
22 | import java.net.InetAddress;
23 | import java.net.UnknownHostException;
24 | import java.security.MessageDigest;
25 |
26 | /**
27 | * 创 建 人: tangchao
28 | * 创建日期: 2016/6/30 14:44
29 | * 修改时间:
30 | * 修改备注:
31 | */
32 | public class Utils {
33 |
34 | private static final String TAG = "Utils";
35 |
36 | //版本名称,显示用
37 | private String versionName = "";
38 | //版本号,升级检查用
39 | private int versionCode = 0;
40 |
41 | private static Utils instance = null;
42 |
43 | private Utils(){}
44 |
45 | public static Utils getInstance() {
46 | if(instance == null) {
47 | instance = new Utils();
48 | }
49 | return instance;
50 | }
51 |
52 | /**
53 | * 获取应用版本名称
54 | * @param ctx
55 | * @return
56 | */
57 | public String getVersionName(Context ctx) {
58 | if(versionName.equals("")) {
59 | getVersionInfo(ctx);
60 | }
61 | ULog.d(TAG, "getVersionName : " + versionName);
62 | return versionName;
63 | }
64 |
65 | /**
66 | * 获取应用版本号
67 | * @param ctx
68 | * @return
69 | */
70 | public int getVersionCode(Context ctx) {
71 | if(versionCode == 0) {
72 | getVersionCode(ctx);
73 | }
74 | ULog.d(TAG, "versionCode : " + versionCode);
75 | return versionCode;
76 | }
77 |
78 | /**
79 | * 获取应用版本信息
80 | * @param ctx
81 | */
82 | private void getVersionInfo(Context ctx) {
83 | try {
84 | PackageManager packageManager = ctx.getPackageManager();
85 | PackageInfo pdkInfo = packageManager.getPackageInfo(ctx.getPackageName(), 0);
86 | versionName = pdkInfo.versionName;
87 | versionCode = pdkInfo.versionCode;
88 | } catch (PackageManager.NameNotFoundException e) {
89 | ULog.e(TAG, "getVersionInfo error! " + e.getMessage());
90 | }
91 | }
92 |
93 | /**
94 | * 检查ip是否连接的通
95 | * @param ip 目标ip地址
96 | * @return 目标ip地址是否连接通畅
97 | */
98 | public boolean isIpReachable(String ip) {
99 | try {
100 | InetAddress addr = InetAddress.getByName(ip);
101 | if (addr.isReachable(3000)) {
102 | return true;
103 | }
104 | return false;
105 | } catch (UnknownHostException e) {
106 | } catch (IOException e) {
107 | }
108 | return false;
109 | }
110 |
111 | /**
112 | * 加载本地图片
113 | * @param url
114 | * @return
115 | */
116 | public Bitmap getLoacalBitmap(String url) {
117 | try {
118 | FileInputStream fis = new FileInputStream(url);
119 | return BitmapFactory.decodeStream(fis); ///把流转化为Bitmap图片
120 | } catch (FileNotFoundException e) {
121 | ULog.e(TAG, "getLoacalBitmap error : " + e.getMessage());
122 | return null;
123 | }
124 | }
125 |
126 | /**
127 | * 根据指定的图像路径和大小来获取缩略图
128 | * 此方法有两点好处:
129 | * 1. 使用较小的内存空间,第一次获取的bitmap实际上为null,只是为了读取宽度和高度,
130 | * 第二次读取的bitmap是根据比例压缩过的图像,第三次读取的bitmap是所要的缩略图。
131 | * 2. 缩略图对于原图像来讲没有拉伸,这里使用了2.2版本的新工具ThumbnailUtils,使
132 | * 用这个工具生成的图像不会被拉伸。
133 | * @param imagePath 图像的路径
134 | * @param width 指定输出图像的宽度
135 | * @param height 指定输出图像的高度
136 | * @return 生成的缩略图
137 | */
138 | public Bitmap getImageThumbnail(String imagePath, int width, int height) {
139 | Bitmap bitmap = null;
140 | BitmapFactory.Options options = new BitmapFactory.Options();
141 | options.inJustDecodeBounds = true;
142 | // 获取这个图片的宽和高,注意此处的bitmap为null
143 | bitmap = BitmapFactory.decodeFile(imagePath, options);
144 | options.inJustDecodeBounds = false; // 设为 false
145 | // 计算缩放比
146 | int h = options.outHeight;
147 | int w = options.outWidth;
148 | int beWidth = w / width;
149 | int beHeight = h / height;
150 | int be = 1;
151 | if (beWidth < beHeight) {
152 | be = beWidth;
153 | } else {
154 | be = beHeight;
155 | }
156 | if (be <= 0) {
157 | be = 1;
158 | }
159 | options.inSampleSize = be;
160 | // 重新读入图片,读取缩放后的bitmap,注意这次要把options.inJustDecodeBounds 设为 false
161 | bitmap = BitmapFactory.decodeFile(imagePath, options);
162 | // 利用ThumbnailUtils来创建缩略图,这里要指定要缩放哪个Bitmap对象
163 | bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,
164 | ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
165 | return bitmap;
166 | }
167 |
168 | /**
169 | * 获取视频的缩略图
170 | * 先通过ThumbnailUtils来创建一个视频的缩略图,然后再利用ThumbnailUtils来生成指定大小的缩略图。
171 | * 如果想要的缩略图的宽和高都小于MICRO_KIND,则类型要使用MICRO_KIND作为kind的值,这样会节省内存。
172 | * @param videoPath 视频的路径
173 | * @param width 指定输出视频缩略图的宽度
174 | * @param height 指定输出视频缩略图的高度度
175 | * @param kind 参照MediaStore.Images.Thumbnails类中的常量MINI_KIND和MICRO_KIND。
176 | * 其中,MINI_KIND: 512 x 384,MICRO_KIND: 96 x 96
177 | * @return 指定大小的视频缩略图
178 | */
179 | public Bitmap getVideoThumbnail(String videoPath, int width, int height,
180 | int kind) {
181 | Bitmap bitmap = null;
182 | // 获取视频的缩略图
183 | ULog.d(TAG, "videopath is : " + videoPath);
184 | bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);
185 | // System.out.println("w"+bitmap.getWidth());
186 | // System.out.println("h"+bitmap.getHeight());
187 | bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height,
188 | ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
189 | return bitmap;
190 | }
191 |
192 |
193 | public Bitmap getVideoThumbnail(ContentResolver cr, Uri uri) {
194 | Bitmap bitmap = null;
195 | BitmapFactory.Options options = new BitmapFactory.Options();
196 | options.inDither = false;
197 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
198 | Cursor cursor = cr.query(uri,new String[] { MediaStore.Video.Media._ID }, null, null, null);
199 |
200 | if (cursor == null || cursor.getCount() == 0) {
201 | return null;
202 | }
203 | cursor.moveToFirst();
204 | String videoId = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media._ID)); //image id in image table.s
205 |
206 | if (videoId == null) {
207 | return null;
208 | }
209 | cursor.close();
210 | long videoIdLong = Long.parseLong(videoId);
211 | bitmap = MediaStore.Video.Thumbnails.getThumbnail(cr, videoIdLong, MediaStore.Images.Thumbnails.MICRO_KIND, options);
212 |
213 | return bitmap;
214 | }
215 |
216 | /**
217 | * 通过文件名 获取视频的缩略图
218 | *
219 | * @param context
220 | * @param cr cr = getContentResolver();
221 | * @param testVideopath 全路径 "/mnt/sdcard/sidamingbu.mp4";
222 | * @return
223 | */
224 | public Bitmap getVideoThumbnail(Context context, String testVideopath) {
225 | // final String testVideopath = "/mnt/sdcard/sidamingbu.mp4";
226 | ContentResolver testcr = context.getContentResolver();
227 | String[] projection = { MediaStore.Video.Media.DATA, MediaStore.Video.Media._ID, };
228 | String whereClause = MediaStore.Video.Media.DATA + " = '" + testVideopath + "'";
229 | Cursor cursor = testcr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, whereClause,
230 | null, null);
231 | int _id = 0;
232 | String videoPath = "";
233 | if (cursor == null || cursor.getCount() == 0) {
234 | return null;
235 | }
236 | if (cursor.moveToFirst()) {
237 |
238 | int _idColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID);
239 | int _dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA);
240 |
241 | do {
242 | _id = cursor.getInt(_idColumn);
243 | videoPath = cursor.getString(_dataColumn);
244 | System.out.println(_id + " " + videoPath);
245 | } while (cursor.moveToNext());
246 | }
247 | BitmapFactory.Options options = new BitmapFactory.Options();
248 | options.inDither = false;
249 | options.inPreferredConfig = Bitmap.Config.ARGB_8888;
250 | Bitmap bitmap = MediaStore.Video.Thumbnails.getThumbnail(testcr, _id, MediaStore.Images.Thumbnails.MICRO_KIND,
251 | options);
252 | return bitmap;
253 | }
254 |
255 |
256 | /**
257 | * 获取目录大小
258 | * @param file
259 | * @return
260 | */
261 | public double getDirSize(File file) {
262 | //判断文件是否存在
263 | if (file.exists()) {
264 | //如果是目录则递归计算其内容的总大小
265 | if (file.isDirectory()) {
266 | File[] children = file.listFiles();
267 | double size = 0;
268 | for (File f : children)
269 | size += getDirSize(f);
270 | return size;
271 | } else {//如果是文件则直接返回其大小,以“kb”为单位
272 | double size = (double) file.length() / 1024;
273 | return size;
274 | }
275 | } else {
276 | ULog.e(TAG, "getDirSize error:" + file.getAbsolutePath() + " is not found.");
277 | return 0.0;
278 | }
279 | }
280 |
281 | /**
282 | * 获取应用程序接收总字节数,包括mobile 和 wifi
283 | * @return
284 | */
285 | int appUid = -1;
286 | public long getUidRxBytes(Context ctx) {
287 | if(appUid == -1) {
288 | try {
289 | appUid = ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES).uid;
290 | } catch (PackageManager.NameNotFoundException e1) {
291 | ULog.e(TAG, "get application uid error: " + e1.getMessage());
292 | }
293 | }
294 | return TrafficStats.getUidRxBytes(appUid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalRxBytes() / 1024);
295 | }
296 |
297 | /**
298 | * 删除目录以及目录下的所有子目录及文件
299 | * @param dir 目录
300 | * @return 是否删除成功
301 | */
302 | public boolean deleteDir(File dir) {
303 | if (dir.isDirectory()) {
304 | String[] children = dir.list();
305 | for (int i = 0; i < children.length; i++) {
306 | boolean success = deleteDir(new File(dir, children[i]));
307 | if (!success) {
308 | return false;
309 | }
310 | }
311 | }
312 | if(dir.isFile()) {
313 | return dir.delete();
314 | }
315 | return true;
316 | }
317 |
318 | /**
319 | * 删除指定文件
320 | * @param file
321 | * @return
322 | */
323 | public boolean deleteFile(String file) {
324 | try {
325 | File delFile = new File(file);
326 | if(delFile.exists()) {
327 | return delFile.delete();
328 | }
329 | } catch (Exception e) {
330 | ULog.e(TAG, "delete File:" + file + "error, " + e.getMessage());
331 | }
332 | return false;
333 | }
334 |
335 | // 网关获取
336 | public String getGateWay(Context context) {
337 | WifiManager wifiManager = (WifiManager) context
338 | .getSystemService(Context.WIFI_SERVICE);
339 | DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
340 |
341 | // dhcpInfo获取的是最后一次成功的相关信息,包括网关、ip等
342 | //return "dh_ip:" + FormatIP(dhcpInfo.ipAddress) + "\n" + "dh_gateway"+ FormatIP(dhcpInfo.gateway);
343 | //return FormatIP(dhcpInfo.gateway);
344 | return long2ip(dhcpInfo.gateway);
345 | }
346 |
347 | // IP地址转化为字符串格式
348 | @SuppressWarnings("deprecation")
349 | public String FormatIP(int IpAddress) {
350 | return Formatter.formatIpAddress(IpAddress);
351 | }
352 |
353 | private String long2ip(long ip){
354 | StringBuffer sb=new StringBuffer();
355 | sb.append(String.valueOf((int)(ip&0xff)));
356 | sb.append('.');
357 | sb.append(String.valueOf((int)((ip>>8)&0xff)));
358 | sb.append('.');
359 | sb.append(String.valueOf((int)((ip>>16)&0xff)));
360 | sb.append('.');
361 | sb.append(String.valueOf((int)((ip>>24)&0xff)));
362 | return sb.toString();
363 | }
364 |
365 | /**
366 | * md5加密
367 | * @param s
368 | * @return
369 | */
370 | public final static String MD5(String s) {
371 | char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
372 | try {
373 | byte[] btInput = s.getBytes();
374 | // 获得MD5摘要算法的 MessageDigest 对象
375 | MessageDigest mdInst = MessageDigest.getInstance("MD5");
376 | // 使用指定的字节更新摘要
377 | mdInst.update(btInput);
378 | // 获得密文
379 | byte[] md = mdInst.digest();
380 | // 把密文转换成十六进制的字符串形式
381 | int j = md.length;
382 | char str[] = new char[j * 2];
383 | int k = 0;
384 | for (int i = 0; i < j; i++) {
385 | byte byte0 = md[i];
386 | str[k++] = hexDigits[byte0 >>> 4 & 0xf];
387 | str[k++] = hexDigits[byte0 & 0xf];
388 | }
389 | return new String(str);
390 | } catch (Exception e) {
391 | e.printStackTrace();
392 | return null;
393 | }
394 | }
395 |
396 | /**
397 | * 获取HttpUtils对象
398 | */
399 |
400 | /* HttpUtils httpUtils = null;
401 | int HTTP_CONNECT_TIMEOUT = 8000;
402 |
403 | private void initHttpUtils() {
404 | if(httpUtils == null) {
405 | httpUtils = new HttpUtils();
406 | }
407 | }
408 | public HttpUtils getHttpUtils() {
409 | initHttpUtils();
410 | httpUtils.configTimeout(HTTP_CONNECT_TIMEOUT);
411 | return httpUtils;
412 | }
413 | public HttpUtils getHttpUtils(int timeout) {
414 | initHttpUtils();
415 | httpUtils.configTimeout(timeout);
416 | return httpUtils;
417 | }*/
418 | }
419 |
--------------------------------------------------------------------------------
/blelib/src/main/java/cn/me/com/blelib/ble/bluetooth/BlueToothMessageListener.java:
--------------------------------------------------------------------------------
1 | package cn.me.com.blelib.ble.bluetooth;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.bluetooth.BluetoothAdapter;
6 | import android.bluetooth.BluetoothDevice;
7 | import android.bluetooth.BluetoothGatt;
8 | import android.bluetooth.BluetoothGattCallback;
9 | import android.bluetooth.BluetoothGattCharacteristic;
10 | import android.bluetooth.BluetoothGattDescriptor;
11 | import android.bluetooth.BluetoothGattService;
12 | import android.bluetooth.BluetoothManager;
13 | import android.bluetooth.BluetoothProfile;
14 | import android.content.Context;
15 | import android.content.pm.PackageManager;
16 | import android.os.Handler;
17 |
18 | import java.util.UUID;
19 |
20 | import cn.me.com.blelib.ble.utils.ULog;
21 |
22 |
23 | /**
24 | * 创 建 人: tangchao
25 | * 创建日期: 2016/6/30 14:37
26 | * 修改时间:
27 | * 修改备注:
28 | */
29 | @SuppressLint("NewApi")
30 | public class BlueToothMessageListener {
31 | //tag
32 | private static final String TAG = "BlueToothMessageListener";
33 | //activity
34 | private Context mContext;
35 | //回调对象
36 | private IBlueToothMessageCallBack btMsgCallBack;
37 | //是否扫描
38 | private boolean mScanning = false;
39 |
40 | //adapter
41 | private BluetoothAdapter mBluetoothAdapter;
42 |
43 | private BluetoothGatt mBluetoothGatt;
44 |
45 |
46 | //蓝牙设备监听端口
47 | String[] deviceReadNotifyUUIDs = null;
48 | int deviceReadNotifyIndex = 0;
49 | BluetoothGattService btService = null;
50 | private Handler mHandler =new Handler();
51 |
52 | private boolean isScan=true;
53 | private boolean isScanByName;
54 | private String serviceUUid;
55 | private String[] notifyUUid;
56 | String writeUUid;
57 | String readUUid;
58 | private String name="iChoice";
59 | private String mac="08:7C:BE:2F:87:BA";
60 | private long SCAN_PERIOD=10000;
61 |
62 | public static BlueToothMessageListener create(Activity activity) {
63 | return new BlueToothMessageListener(activity);
64 | }
65 |
66 |
67 | public BlueToothMessageListener(Context activity ) {
68 | this.mContext = activity;
69 |
70 | }
71 | public BlueToothMessageListener setCallback(IBlueToothMessageCallBack callback){
72 | this.btMsgCallBack=callback;
73 | return this;
74 | }
75 | public BlueToothMessageListener setScanTime(Long time){
76 | this.SCAN_PERIOD=time;
77 | return this;
78 | }
79 | public BlueToothMessageListener setServiceUUid(String serviceUUid){
80 | this.serviceUUid=serviceUUid;
81 | return this;
82 | }
83 | public BlueToothMessageListener setNotifyUUid(String[] notifyUUid){
84 | this.notifyUUid=notifyUUid;
85 | return this;
86 | }
87 | public BlueToothMessageListener setReadUUid(String readUUid){
88 | this.readUUid=readUUid;
89 | return this;
90 | }
91 | public BlueToothMessageListener setWriteUUid(String writeUUid){
92 | this.writeUUid=writeUUid;
93 | return this;
94 | }
95 | public BlueToothMessageListener setBleName(String name){
96 | this.name=name;
97 | return this;
98 | }
99 | public BlueToothMessageListener setBleMac(String mac){
100 | this.mac=mac;
101 | return this;
102 | }
103 | public int checkBle(){
104 |
105 | // 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
106 | if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
107 | return BleConfig.START_DEVICE_UNSUPPORTBLE;
108 | }
109 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
110 |
111 | // 初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
112 | BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
113 | mBluetoothAdapter = bluetoothManager.getAdapter();
114 | }else {
115 | return BleConfig.START_DEVICE_VERSON;
116 | }
117 |
118 | // 检查设备上是否支持蓝牙
119 | if (mBluetoothAdapter == null) {
120 | return BleConfig.START_DEVICE_UNSUPPORTBT;
121 | }
122 |
123 | // 如果蓝牙没有打开,则直接打开
124 | if (!mBluetoothAdapter.isEnabled()) {
125 | mBluetoothAdapter.enable();
126 | }
127 |
128 | return BleConfig.START_DEVICE_SUCCESS;
129 | }
130 |
131 | /**
132 | * 开始监听蓝牙消息
133 | * @return 0成功,其他失败
134 | */
135 | public void startListener(boolean isScanByName) {
136 | this.isScanByName=isScanByName;
137 | new Handler().postDelayed(new Runnable() {
138 | @Override
139 | public void run() {
140 | scanLeDevice(true);
141 | }
142 | }, 100);//开始扫描周围蓝牙设备
143 | isScan=true;
144 |
145 |
146 | }
147 |
148 | /**
149 | * 关闭蓝牙消息监听
150 | */
151 | public void stopListenerMessage() {
152 | mScanning=true;
153 | isScan=false;
154 | if (mBluetoothAdapter!=null)
155 | scanLeDevice(false);
156 |
157 | if (mBluetoothGatt!=null) {
158 | mBluetoothGatt.disconnect();
159 | mBluetoothGatt = null;
160 | }
161 |
162 |
163 | }
164 |
165 | @SuppressWarnings("unused")
166 | public void restartListenerMessage() {
167 | stopListenerMessage();
168 | startListener(isScanByName);
169 |
170 | }
171 |
172 | //扫描设备
173 | public void scanLeDevice(boolean enable) {
174 | if (enable) {
175 | mScanning = true;
176 | mBluetoothAdapter.startLeScan(mLeScanCallback);
177 | } else {
178 | mScanning = false;
179 | mBluetoothAdapter.stopLeScan(mLeScanCallback);
180 | }
181 | }
182 |
183 | //扫描设备
184 | /* public void scanLeDevice( boolean enable) {
185 | if (enable) {
186 | // Stops scanning after a pre-defined scan period.
187 | mHandler.postDelayed(new Runnable() {
188 | @Override
189 | public void run() {
190 | mScanning = false;
191 | mBluetoothAdapter.stopLeScan(mLeScanCallback);
192 | }
193 | }, SCAN_PERIOD);
194 |
195 | mScanning = true;
196 | mBluetoothAdapter.startLeScan(mLeScanCallback);
197 | } else {
198 | mScanning = false;
199 | mBluetoothAdapter.stopLeScan(mLeScanCallback);
200 | }
201 |
202 | }*/
203 |
204 |
205 | // Device scan callback.
206 | private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
207 |
208 | @Override
209 | public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
210 | ULog.d(TAG,"onscan");
211 | // BluetoothDevice name=eBody-Scale address=BC:6A:29:26:97:5E
212 | ULog.d(TAG,"BluetoothDevice name=" + device.getName() + " address=" + device.getAddress());
213 | // BluetoothDevice name=eBody-Scale address=BC:6A:29:26:97:5E
214 | //根据蓝牙名称或者mac地址找到对应的蓝牙设备
215 | if (isScanByName){
216 | if (name.equals(device.getName())) {
217 | ULog.d(TAG,"find_device_by_name");
218 | mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
219 | if (mScanning) {
220 | scanLeDevice(false);
221 | }
222 |
223 | }
224 | }else {
225 | if (mac.equals(device.getAddress())) {
226 | ULog.d(TAG,"find_device_by_mac");
227 | mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
228 | if (mScanning) {
229 | scanLeDevice(false);
230 | }
231 |
232 | }
233 | }
234 |
235 |
236 |
237 |
238 |
239 | }
240 | };
241 |
242 |
243 | //连接回调信息
244 | private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
245 | @Override
246 | public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
247 | //连接成功判断
248 | if (newState == BluetoothProfile.STATE_CONNECTED) {
249 |
250 | ULog.d(TAG,"connected");
251 | btMsgCallBack.onConnected();
252 | mBluetoothGatt.discoverServices();
253 | // 连接断开判断
254 | } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
255 | ULog.d(TAG,"onDisConnected");
256 | btMsgCallBack.onDisConnected();
257 | gatt.close();
258 |
259 | //连接断开延时一秒后继续扫秒蓝牙连接
260 | try {
261 | Thread.sleep(100);
262 | } catch (InterruptedException e) {
263 | e.printStackTrace();
264 | }
265 | if (isScan)
266 | scanLeDevice(true);
267 |
268 |
269 | } else if (status != BluetoothGatt.GATT_SUCCESS) { // 连接失败判断
270 | ULog.d(TAG,"onConnectFail");
271 | btMsgCallBack.onConnectFail();
272 |
273 | try {
274 | Thread.sleep(100);
275 | } catch (InterruptedException e) {
276 | e.printStackTrace();
277 | }
278 | if (isScan)
279 | scanLeDevice(true);
280 | }
281 | }
282 |
283 | @Override
284 | public void onServicesDiscovered(BluetoothGatt gatt, int status) {
285 | btMsgCallBack.onServicesDiscovered();
286 | //发现服务后的回调
287 | if (status == BluetoothGatt.GATT_SUCCESS) {
288 | //搜寻设备完毕,写入数据特征到设备中
289 |
290 | if (mBluetoothAdapter == null || mBluetoothGatt == null) {
291 | return;
292 | }
293 | if (serviceUUid==null){
294 | ULog.i(TAG," serviceUUid is null");
295 | return;
296 | }
297 | btService = mBluetoothGatt.getService(UUID.fromString(serviceUUid));
298 | if (btService == null) {
299 | gatt.disconnect(); //找不到服务重新连接
300 | return;
301 | }
302 | ULog.d(TAG,"findServices");
303 |
304 | if (notifyUUid==null){
305 | ULog.i(TAG," notifyUUid is null");
306 | return;
307 | }
308 |
309 | //数据通知uuid列表
310 | deviceReadNotifyIndex = 0;
311 |
312 | BluetoothGattCharacteristic characteristic = btService.getCharacteristic(UUID.fromString(notifyUUid[0]));
313 | if (characteristic != null) {
314 | mBluetoothGatt.setCharacteristicNotification(characteristic, true);
315 | BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(BleConfig.CLIENT_CHARACTERISTIC_CONFIG));
316 | if (descriptor != null) {
317 | descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
318 | mBluetoothGatt.writeDescriptor(descriptor);
319 | }
320 | // mBluetoothGatt.readCharacteristic(characteristic);
321 | }
322 |
323 | } else {
324 | ULog.w(TAG, "onServicesDiscovered received: " + status);
325 | }
326 | }
327 |
328 | public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor gattDescriptor, int status) {
329 |
330 | btMsgCallBack.onDescriptorWrite();
331 | if (status != 0) {
332 | ULog.d(TAG, "onDescriptorWrite, status not 0, do disconnect.");
333 | //状态码出错,先断开连接然后再重新连接
334 | gatt.disconnect();
335 | }else {
336 | if (notifyUUid.length - 1 == deviceReadNotifyIndex) {
337 | //这里通知前端,设备连接成功
338 | btMsgCallBack.onDescriptorWriteSuccess();
339 | ULog.d(TAG,"onDescriptorWriteSuccess");
340 |
341 |
342 | } else {
343 | deviceReadNotifyIndex++;
344 | BluetoothGattCharacteristic characteristic = btService.getCharacteristic(UUID.fromString(notifyUUid[deviceReadNotifyIndex]));
345 | if (characteristic != null) {
346 | mBluetoothGatt.setCharacteristicNotification(characteristic, true);
347 | BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(BleConfig.CLIENT_CHARACTERISTIC_CONFIG));
348 | if (descriptor != null) {
349 | descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
350 | mBluetoothGatt.writeDescriptor(descriptor);
351 | }
352 | mBluetoothGatt.readCharacteristic(characteristic);
353 | }
354 | }
355 | }
356 |
357 | }
358 |
359 |
360 |
361 | @Override
362 | public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
363 | //读取到数据
364 |
365 | ULog.i(TAG, "onCharacteristicRead");
366 | if (status == BluetoothGatt.GATT_SUCCESS) {
367 | ULog.i("TAG", characteristic.getValue().toString());
368 | btMsgCallBack.onCharacteristicRead(characteristic.getValue().toString());
369 |
370 | }
371 | }
372 |
373 | /**
374 | * 返回数据。
375 | */
376 | @Override
377 | public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
378 | // 数据
379 | ULog.d(TAG,"onCharacteristicChanged");
380 | StringBuilder sb = new StringBuilder();
381 | for (int i = 0; i < characteristic.getValue().length; i++) {
382 | // sb.append (characteristic.getValue()[i] & 0xff).append(" ") ; //变成int字符串数据,方便处理
383 | //这里也可变为16进制数据,方便对协议
384 | sb.append (String.format("%02X ",characteristic.getValue()[i] & 0xff)).append(" ") ;
385 | }
386 |
387 | btMsgCallBack.onReceiveMessage(sb.toString());
388 |
389 | }
390 | };
391 |
392 | /**
393 | * 写入数据到设备
394 | * @param bb
395 | */
396 | public void writeLlsAlertLevel(byte[] bb) {
397 |
398 | if (btService == null) {
399 | ULog.e(TAG, "link loss Alert service not found!");
400 | return;
401 | }
402 | if (writeUUid==null){
403 | ULog.i(TAG,"writeUUid is null");
404 | return;
405 | }
406 | BluetoothGattCharacteristic alertLevel = btService.getCharacteristic(UUID.fromString(writeUUid));
407 |
408 | if (alertLevel == null) {
409 | ULog.e(TAG, "link loss Alert Level charateristic not found!");
410 | return;
411 | }
412 |
413 | boolean status = false;
414 | int storedLevel = alertLevel.getWriteType();
415 | ULog.d(TAG, "storedLevel() - storedLevel=" + storedLevel);
416 | alertLevel.setValue(bb);
417 | alertLevel.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
418 | status = mBluetoothGatt.writeCharacteristic(alertLevel);
419 | ULog.d(TAG, "writeLlsAlertLevel() - status=" + status);
420 | }
421 | }
422 |
--------------------------------------------------------------------------------