Browse Source

1.测试例项目开发

slambb 4 năm trước cách đây
commit
ed3a01ca77
100 tập tin đã thay đổi với 2655 bổ sung0 xóa
  1. 9 0
      .gitignore
  2. BIN
      .idea/caches/build_file_checksums.ser
  3. 29 0
      .idea/codeStyles/Project.xml
  4. 19 0
      .idea/gradle.xml
  5. 33 0
      .idea/misc.xml
  6. 10 0
      .idea/modules.xml
  7. 12 0
      .idea/runConfigurations.xml
  8. 1 0
      app/.gitignore
  9. 30 0
      app/build.gradle
  10. 21 0
      app/proguard-rules.pro
  11. 26 0
      app/src/androidTest/java/com/slam/bboxble/ExampleInstrumentedTest.java
  12. 29 0
      app/src/main/AndroidManifest.xml
  13. 838 0
      app/src/main/java/com/slam/bboxble/BekenOTAFragment.java
  14. 360 0
      app/src/main/java/com/slam/bboxble/DeviceControlActivity.java
  15. 442 0
      app/src/main/java/com/slam/bboxble/DeviceScanActivity.java
  16. 36 0
      app/src/main/java/com/slam/bboxble/FileInfo.java
  17. 59 0
      app/src/main/java/com/slam/bboxble/FileUnit.java
  18. 91 0
      app/src/main/java/com/slam/bboxble/OTAFileAdapter.java
  19. 321 0
      app/src/main/java/com/slam/bboxble/ServiceFragment.java
  20. 218 0
      app/src/main/java/com/slam/bboxble/UUIDAdapter_2.java
  21. 37 0
      app/src/main/java/com/slam/bboxble/UUIDCheckList.java
  22. BIN
      app/src/main/res/drawable-hdpi/beken_logo.png
  23. BIN
      app/src/main/res/drawable-hdpi/beken_logo_full.jpg
  24. BIN
      app/src/main/res/drawable-hdpi/device.png
  25. BIN
      app/src/main/res/drawable-hdpi/ic_1489773184_device_power_outline_stroke.png
  26. BIN
      app/src/main/res/drawable-hdpi/ic_1489773512_device_power_glyph.png
  27. BIN
      app/src/main/res/drawable-hdpi/ic_action_about.png
  28. BIN
      app/src/main/res/drawable-hdpi/ic_action_bluetooth.png
  29. BIN
      app/src/main/res/drawable-hdpi/ic_action_cancel.png
  30. BIN
      app/src/main/res/drawable-hdpi/ic_action_refresh.png
  31. BIN
      app/src/main/res/drawable-hdpi/ic_action_settings.png
  32. BIN
      app/src/main/res/drawable-hdpi/ic_bluetooth_connected_black_48dp.png
  33. BIN
      app/src/main/res/drawable-hdpi/ic_bluetooth_disabled_black_48dp.png
  34. BIN
      app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png
  35. BIN
      app/src/main/res/drawable-hdpi/ic_delete_forever_black_24dp.png
  36. BIN
      app/src/main/res/drawable-hdpi/ic_highlight_black_24dp.png
  37. BIN
      app/src/main/res/drawable-hdpi/ic_highlight_off_black_24dp.png
  38. BIN
      app/src/main/res/drawable-hdpi/ic_launcher.png
  39. BIN
      app/src/main/res/drawable-hdpi/ic_play_arrow_black_24dp.png
  40. BIN
      app/src/main/res/drawable-hdpi/ic_portable_wifi_off_black_48dp.png
  41. BIN
      app/src/main/res/drawable-hdpi/ic_replay_black_24dp.png
  42. BIN
      app/src/main/res/drawable-hdpi/ic_stop_black_24dp.png
  43. BIN
      app/src/main/res/drawable-hdpi/ic_wifi_tethering_black_48dp.png
  44. BIN
      app/src/main/res/drawable-hdpi/tile.9.png
  45. BIN
      app/src/main/res/drawable-mdpi/beken_logo.png
  46. BIN
      app/src/main/res/drawable-mdpi/beken_logo_full.jpg
  47. BIN
      app/src/main/res/drawable-mdpi/device.png
  48. BIN
      app/src/main/res/drawable-mdpi/ic_1489773184_device_power_outline_stroke.png
  49. BIN
      app/src/main/res/drawable-mdpi/ic_1489773512_device_power_glyph.png
  50. BIN
      app/src/main/res/drawable-mdpi/ic_action_about.png
  51. BIN
      app/src/main/res/drawable-mdpi/ic_action_bluetooth.png
  52. BIN
      app/src/main/res/drawable-mdpi/ic_action_cancel.png
  53. BIN
      app/src/main/res/drawable-mdpi/ic_action_refresh.png
  54. BIN
      app/src/main/res/drawable-mdpi/ic_action_settings.png
  55. BIN
      app/src/main/res/drawable-mdpi/ic_bluetooth_connected_black_48dp.png
  56. BIN
      app/src/main/res/drawable-mdpi/ic_bluetooth_disabled_black_48dp.png
  57. BIN
      app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png
  58. BIN
      app/src/main/res/drawable-mdpi/ic_delete_forever_black_24dp.png
  59. BIN
      app/src/main/res/drawable-mdpi/ic_highlight_black_24dp.png
  60. BIN
      app/src/main/res/drawable-mdpi/ic_highlight_off_black_24dp.png
  61. BIN
      app/src/main/res/drawable-mdpi/ic_launcher.png
  62. BIN
      app/src/main/res/drawable-mdpi/ic_play_arrow_black_24dp.png
  63. BIN
      app/src/main/res/drawable-mdpi/ic_portable_wifi_off_black_48dp.png
  64. BIN
      app/src/main/res/drawable-mdpi/ic_replay_black_24dp.png
  65. BIN
      app/src/main/res/drawable-mdpi/ic_stop_black_24dp.png
  66. BIN
      app/src/main/res/drawable-mdpi/ic_wifi_tethering_black_48dp.png
  67. 34 0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  68. BIN
      app/src/main/res/drawable-xhdpi/beken_logo.png
  69. BIN
      app/src/main/res/drawable-xhdpi/beken_logo_full.jpg
  70. BIN
      app/src/main/res/drawable-xhdpi/device.png
  71. BIN
      app/src/main/res/drawable-xhdpi/ic_1489773184_device_power_outline_stroke.png
  72. BIN
      app/src/main/res/drawable-xhdpi/ic_1489773512_device_power_glyph.png
  73. BIN
      app/src/main/res/drawable-xhdpi/ic_action_about.png
  74. BIN
      app/src/main/res/drawable-xhdpi/ic_action_bluetooth.png
  75. BIN
      app/src/main/res/drawable-xhdpi/ic_action_cancel.png
  76. BIN
      app/src/main/res/drawable-xhdpi/ic_action_refresh.png
  77. BIN
      app/src/main/res/drawable-xhdpi/ic_action_settings.png
  78. BIN
      app/src/main/res/drawable-xhdpi/ic_bluetooth_connected_black_48dp.png
  79. BIN
      app/src/main/res/drawable-xhdpi/ic_bluetooth_disabled_black_48dp.png
  80. BIN
      app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png
  81. BIN
      app/src/main/res/drawable-xhdpi/ic_delete_forever_black_24dp.png
  82. BIN
      app/src/main/res/drawable-xhdpi/ic_highlight_black_24dp.png
  83. BIN
      app/src/main/res/drawable-xhdpi/ic_highlight_off_black_24dp.png
  84. BIN
      app/src/main/res/drawable-xhdpi/ic_launcher.png
  85. BIN
      app/src/main/res/drawable-xhdpi/ic_play_arrow_black_24dp.png
  86. BIN
      app/src/main/res/drawable-xhdpi/ic_portable_wifi_off_black_48dp.png
  87. BIN
      app/src/main/res/drawable-xhdpi/ic_replay_black_24dp.png
  88. BIN
      app/src/main/res/drawable-xhdpi/ic_stop_black_24dp.png
  89. BIN
      app/src/main/res/drawable-xhdpi/ic_wifi_tethering_black_48dp.png
  90. BIN
      app/src/main/res/drawable-xxhdpi/beken_logo.png
  91. BIN
      app/src/main/res/drawable-xxhdpi/beken_logo_full.jpg
  92. BIN
      app/src/main/res/drawable-xxhdpi/device.png
  93. BIN
      app/src/main/res/drawable-xxhdpi/ic_1489773184_device_power_outline_stroke.png
  94. BIN
      app/src/main/res/drawable-xxhdpi/ic_1489773512_device_power_glyph.png
  95. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_about.png
  96. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_bluetooth.png
  97. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
  98. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_refresh.png
  99. BIN
      app/src/main/res/drawable-xxhdpi/ic_action_settings.png
  100. BIN
      app/src/main/res/drawable-xxhdpi/ic_bluetooth_connected_black_48dp.png

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild

BIN
.idea/caches/build_file_checksums.ser


+ 29 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,29 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <Objective-C-extensions>
+      <file>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+      </file>
+      <class>
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+        <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+      </class>
+      <extensions>
+        <pair source="cpp" header="h" fileNamingConvention="NONE" />
+        <pair source="c" header="h" fileNamingConvention="NONE" />
+      </extensions>
+    </Objective-C-extensions>
+  </code_scheme>
+</component>

+ 19 - 0
.idea/gradle.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/bboxblelib" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 33 - 0
.idea/misc.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>

+ 10 - 0
.idea/modules.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/BBOXBLE.iml" filepath="$PROJECT_DIR$/BBOXBLE.iml" />
+      <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
+      <module fileurl="file://$PROJECT_DIR$/bboxblelib/bboxblelib.iml" filepath="$PROJECT_DIR$/bboxblelib/bboxblelib.iml" />
+    </modules>
+  </component>
+</project>

+ 12 - 0
.idea/runConfigurations.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 30 - 0
app/build.gradle

@@ -0,0 +1,30 @@
+apply plugin: 'com.android.application'
+//apply plugin: 'com.android.library'
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "com.slam.bboxble"
+        minSdkVersion 19
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+
+dependencies {
+    implementation fileTree(include: ['*.jar'], dir: 'libs')
+    implementation 'com.android.support:appcompat-v7:26.0.0-beta1'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:0.5'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
+    implementation 'org.greenrobot:eventbus:3.0.0'
+    implementation project(':bboxblelib')
+}

+ 21 - 0
app/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 26 - 0
app/src/androidTest/java/com/slam/bboxble/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.slam.bboxble;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() throws Exception {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.slam.bboxble", appContext.getPackageName());
+    }
+}

+ 29 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,29 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.slam.bboxble">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme" >
+
+        <activity android:name="com.slam.bboxble.DeviceScanActivity"
+            android:label="@string/app_name"
+            android:configChanges="orientation"
+            android:screenOrientation="portrait">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+        <activity android:name="com.slam.bboxble.DeviceControlActivity"
+            android:configChanges="orientation"
+            android:screenOrientation="portrait"
+            android:windowSoftInputMode="stateHidden|adjustPan"/>
+        <service android:name="com.slam.bboxblelib.BluetoothLeService" android:enabled="true"/>
+    </application>
+
+
+</manifest>

+ 838 - 0
app/src/main/java/com/slam/bboxble/BekenOTAFragment.java

@@ -0,0 +1,838 @@
+package com.slam.bboxble;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.slam.bboxblelib.Conversion;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Created by lenovo on 2017/9/15.
+ */
+
+public class BekenOTAFragment extends Fragment implements View.OnClickListener {
+
+    private final String TAG = BekenOTAFragment.class.getSimpleName();
+    private Button mButtonToUUID, mButtonOTA, mButtonStartOTA, mButtonStopOTA, mButtonRefresh, mButtonFileList;
+    private ListView mOTAListView;
+    private int OTAType = 0;
+    private final int MaxRetry = 2000;
+    private HashMap<String, FileInfo> mOTAFlieList = null;
+    private ArrayList<String> mFileList;
+//    private int mTimeoutValue = MaxRetry;
+
+    private TextView mProgressInfo;
+    private ProgressBar mProgressBar;
+    private int mReadyToUpdate = 0;
+    private long mAlreadyReadCount = 0;
+    private TextView mTextViewDeviceVersion, mTextViewFileVersion, mTextViewFilePath;
+    private TextView mTextViewDeviceRomVersion, mTextViewOTARomVersion;
+    private boolean isOTADone = false;
+    private boolean canGo = false;
+
+    private boolean flagTag = false;
+    private boolean ifBlockSend = false;
+    private static final int FILE_BUFFER_SIZE = 0x40000;
+    private static final int OAD_BLOCK_SIZE = 16;
+    private static final int HAL_FLASH_WORD_SIZE = 4;
+    private static final int OAD_BUFFER_SIZE = 2 + OAD_BLOCK_SIZE;
+    private final byte[] mFileBuffer = new byte[FILE_BUFFER_SIZE];
+    private byte[] mOadBuffer = new byte[OAD_BUFFER_SIZE];
+    private ImgHdr mFileImgHdr = new ImgHdr();
+    //private ImgHdr mfileImgRomHdr = new ImgHdr();
+    private Timer mTimer = null;
+    private ProgInfo mProgInfo = new ProgInfo();
+    private TimerTask mTimerTask = null;
+    private long lastBlockReq = 0;
+    private static final long TIMER_INTERVAL = 1000;
+    private static final int SEND_INTERVAL = 10;
+    private final Lock mLock = new ReentrantLock();
+    private boolean mProgramming = false;
+    private int DelayTimer = 2;
+    private Uri mFilePath;
+    private int MAXNotify = 10;
+    private byte[] mFileIndexBuffer;
+
+    private OTAFileAdapter mOTAFileAdapter;
+
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.fragment_beken_ota, container, false);
+
+        mOTAListView = (ListView) view.findViewById(R.id.list_ota_files);
+        mProgressInfo = (TextView) view.findViewById(R.id.tw_info);
+        mProgressBar = (ProgressBar) view.findViewById(R.id.pb_progress);
+        mButtonOTA = (Button) view.findViewById(R.id.button_OtaToOTA);
+        mButtonToUUID = (Button) view.findViewById(R.id.button_OtaToUUid);
+        mButtonStartOTA = (Button) view.findViewById(R.id.button_start_ota);
+        mButtonStopOTA = (Button) view.findViewById(R.id.button_stop_ota);
+        mButtonRefresh = (Button) view.findViewById(R.id.button_refresh);
+        mButtonFileList = (Button) view.findViewById(R.id.button);
+        mTextViewDeviceVersion = (TextView) view.findViewById(R.id.text_DeviceVersion);
+        mTextViewFileVersion = (TextView) view.findViewById(R.id.textview_OTAVersion);
+        mTextViewFilePath = (TextView) view.findViewById(R.id.textview_file_path);
+
+        mTextViewDeviceRomVersion = (TextView) view.findViewById(R.id.textview_DeviceRomVersion);
+        mTextViewOTARomVersion = (TextView) view.findViewById(R.id.textview_OTARomVersion);
+
+        mButtonFileList.setOnClickListener(this);
+        mButtonOTA.setOnClickListener(this);
+        mButtonToUUID.setOnClickListener(this);
+        mButtonStartOTA.setOnClickListener(this);
+        mButtonStopOTA.setOnClickListener(this);
+        mButtonRefresh.setOnClickListener(this);
+
+        mButtonStopOTA.setVisibility(View.GONE);
+
+        mButtonStartOTA.setEnabled(false);
+        return view;
+    }
+
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        prepareDate();
+        mOTAFileAdapter = new OTAFileAdapter(getContext(), mOTAFlieList, R.layout.listitem_script, mFileList);
+        mOTAListView.setAdapter(mOTAFileAdapter);
+
+        mOTAListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
+                if (!mProgramming) {
+                    mOTAFileAdapter.init();
+                    mOTAFileAdapter.notifyDataSetChanged();
+                    CheckBox lCheckBox = (CheckBox) view.getTag();
+                    lCheckBox.toggle();
+                    mOTAFileAdapter.isSelected.put(i, lCheckBox.isChecked());
+                    String filePath = FileUnit.getOTAFilePath() + "/" + mOTAFileAdapter.getCheckedFileName();
+                    if (lCheckBox.isChecked()) {
+                        if(getFileVerion(filePath))
+                        {
+                            mTextViewFilePath.setText(mOTAFileAdapter.getCheckedFileName());
+                            if(!mButtonStartOTA.isEnabled())
+                            {
+                                mButtonStartOTA.setEnabled(true);
+                            }
+                        }else
+                        {
+                            mOTAFileAdapter.init();
+                            mOTAFileAdapter.notifyDataSetChanged();
+                        }
+                    }else
+                    {
+                        mTextViewFilePath.setText("");
+                        mTextViewFileVersion.setText("");
+                        mTextViewOTARomVersion.setText("");
+
+                        if(mButtonStartOTA.isEnabled())
+                        {
+                            mButtonStartOTA.setEnabled(false);
+                        }
+                    }
+                }
+            }
+        });
+    }
+
+    private void prepareDate() {
+        mOTAFlieList = new HashMap<String, FileInfo>();
+        File lFolderFile = new File(FileUnit.getOTAFilePath());
+        mFileList = new ArrayList<String>();
+        if (lFolderFile.listFiles() != null) {
+
+            int size = lFolderFile.listFiles().length;
+
+            for (int forCount = 0; forCount < size; forCount++) {
+                File lFile = lFolderFile.listFiles()[forCount];
+                FileInfo lFileInfo = new FileInfo(lFile.toString(), lFile.getName());
+                if (lFileInfo.getFileName().endsWith(".bin")) {
+                    mFileList.add(lFileInfo.getFileName());
+                    mOTAFlieList.put(lFile.getName(), lFileInfo);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        switch (v.getId()) {
+            case R.id.button_OtaToOTA:
+                break;
+            case R.id.button_OtaToUUid:
+                if (!mProgramming) {
+                    ((DeviceControlActivity) getActivity()).changeFragment(2);
+                }
+                break;
+            case R.id.button_start_ota:
+                flagTag = false;
+                isOTADone = false;
+                if(mTextViewDeviceVersion.getText().length()== 0){
+                    Toast.makeText(getContext(), "check device version fail", Toast.LENGTH_SHORT).show();
+                    ((DeviceControlActivity) getActivity()).letGetVersionTrigger();
+                    ((DeviceControlActivity) getActivity()).getmBluetoothLeService().writeOTAIdentfy(new byte[]{0x00});
+                    if(MAXNotify > 0)
+                    {
+                        MAXNotify--;
+                    }
+                    if(MAXNotify == 0)
+                    {
+                        ((DeviceControlActivity) getActivity()).ByeByeFunction();
+                    }
+                    break;
+                }else if (mOTAFileAdapter.getCheckedFileName() != null) {
+                    String filePath = FileUnit.getOTAFilePath() + "/" + mOTAFileAdapter.getCheckedFileName();
+                    Log.e(TAG, filePath);
+
+                    if(OTAType == 2 && mTextViewOTARomVersion.getText().toString().equals(mTextViewDeviceRomVersion.getText().toString()))
+                    {
+                        Toast.makeText(getContext(), "rom version the same", Toast.LENGTH_SHORT).show();
+                        break;
+                    }
+
+                    if (OTAType == 1) {
+
+                        if(mTextViewDeviceVersion.getText().toString().equals(mTextViewFileVersion.getText().toString()))
+                        {
+                            Toast.makeText(getContext(), "version the same", Toast.LENGTH_SHORT).show();
+                            break;
+                        }else if(!mTextViewOTARomVersion.getText().toString().equals(mTextViewDeviceRomVersion.getText().toString()))
+                        {
+                            Toast.makeText(getContext(), "rom version not the same", Toast.LENGTH_SHORT).show();
+                            break;
+                        }
+                    }
+
+                    if(OTAType == 0) break;
+                    loadFile(filePath);
+
+                    mProgressBar.setProgress(0);
+//                    mButtonStartOTA.setVisibility(View.GONE);
+//                    mButtonStopOTA.setVisibility((View.VISIBLE));
+                    mButtonStartOTA.setEnabled(false);
+                    startProgramming();
+                }else if (mTextViewFilePath.getText().length() > 0 ){
+//                    if(mTextViewFilePath.getText().toString().endsWith(".bin")) {
+
+                    if(OTAType == 2 && mTextViewOTARomVersion.getText().toString().equals(mTextViewDeviceRomVersion.getText().toString()))
+                    {
+                        Toast.makeText(getContext(), "rom version the same", Toast.LENGTH_SHORT).show();
+                        break;
+                    }
+
+                    if (OTAType == 1) {
+
+                        if(mTextViewDeviceVersion.getText().toString().equals(mTextViewFileVersion.getText().toString()))
+                        {
+                            Toast.makeText(getContext(), "version the same", Toast.LENGTH_SHORT).show();
+                            break;
+                        }else if(!mTextViewOTARomVersion.getText().toString().equals(mTextViewDeviceRomVersion.getText().toString()))
+                        {
+                            Toast.makeText(getContext(), "rom version not the same", Toast.LENGTH_SHORT).show();
+                            break;
+                        }
+                    }
+                    if(OTAType == 0) break;
+                        loadFile();
+                        mProgressBar.setProgress(0);
+                        mButtonStartOTA.setEnabled(false);
+                        startProgramming();
+//                    }else
+//                    {
+//                        Toast.makeText(getContext(), "not a .bin file", Toast.LENGTH_SHORT).show();
+//                    }
+                }
+                else {
+                    Toast.makeText(getContext(), "Choose a file first", Toast.LENGTH_SHORT).show();
+                }
+                break;
+            case R.id.button_stop_ota:
+//                mButtonStartOTA.setVisibility(View.VISIBLE);
+//                mButtonStopOTA.setVisibility((View.GONE));
+                //mButtonStartOTA.setEnabled(true);
+                stopProgramming();
+                break;
+            case R.id.button_refresh:
+                if (!mProgramming) {
+                    prepareDate();
+                    mTextViewFileVersion.setText("");
+                    mTextViewDeviceVersion.setText("");
+                    mTextViewDeviceRomVersion.setText("");
+                    mTextViewFilePath.setText("");
+                    mFilePath = null;
+                    ((DeviceControlActivity) getActivity()).letGetVersionTrigger();
+                    ((DeviceControlActivity) getActivity()).getmBluetoothLeService().writeOTAIdentfy(new byte[]{0x00});
+                    mOTAFileAdapter = new OTAFileAdapter(getContext(), mOTAFlieList, R.layout.listitem_script, mFileList);
+                    mOTAListView.setAdapter(mOTAFileAdapter);
+                }
+                break;
+            case R.id.button:
+                if(!mProgramming) {
+//                    ((DeviceControlActivity) getActivity()).VersTest();
+                }
+                break;
+            default:
+                break;
+        }
+    }
+
+    private class OadTask implements Runnable {
+        int x = 0;
+
+        @Override
+        public void run() {
+            while (mProgramming) {
+                try {
+                    x = x + SEND_INTERVAL;
+                    Thread.sleep(SEND_INTERVAL);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                //shenzheng beken nubia cell phone can not handle this loading
+                for (int i = 0; (i < 4) & mProgramming; ) {
+                    {
+                        if (flagTag) {
+
+                            if (mReadyToUpdate > 0) {
+//                                flag = programBlock();
+                                mLock.lock();
+                                programBlock();
+                                mLock.unlock();
+                                i++;
+                                if(DelayTimer > 2)
+                                {
+                                    DelayTimer--;
+                                }
+                            }
+
+                            try {
+                                x = x + DelayTimer;
+                                Thread.sleep(DelayTimer);
+                            } catch (InterruptedException e) {
+                                e.printStackTrace();
+                            }
+                        } else {
+                            break;
+                        }
+                    }
+                }
+                //one second update progress once
+                if (x >= 1000) {
+                    x = x % 1000;
+                    try {
+                        ((DeviceControlActivity) getActivity()).runOnUiThread(new Runnable() {
+                            public void run() {
+                                displayStats();
+                            }
+                        });
+                    } catch (NullPointerException e) {
+                        Log.e(TAG, "something wrong 2");
+                    }
+                }
+            }
+        }
+    }
+
+    private void startProgramming() {
+        mProgramming = true;
+
+        DelayTimer = 2;
+        byte[] buf = new byte[16];
+        System.arraycopy(mFileBuffer, 0, buf, 0, 16);
+
+//        [chengyi| add for match sensorTag]
+//        byte[] buf = new byte[OAD_IMG_HDR_SIZE + 2 + 2 + 2];
+//        buf[0] = Conversion.loUint16(mFileImgHdr.ver);
+//        buf[1] = Conversion.hiUint16(mFileImgHdr.ver);
+//        buf[2] = 0x00;
+//        buf[3] = 0x00;
+//        buf[4] = Conversion.loUint16(mFileImgHdr.len);
+//        buf[5] = Conversion.hiUint16(mFileImgHdr.len);
+//        System.arraycopy(mFileImgHdr.uid, 0, buf, 6, 4);
+        //[chengYi| add for show btye array data]
+
+        StringBuilder stringBuilder = new StringBuilder(buf.length);
+        for (byte byteChar : buf) {
+            stringBuilder.append(String.format("%02x ", byteChar));
+        }
+        Log.e(TAG, "first data for ffc1 " + stringBuilder.toString());
+        //[chengYi| end]
+
+        // Send image notification
+        boolean success = ((DeviceControlActivity) getActivity()).getmBluetoothLeService().writeOTAIdentfy(buf);
+
+        // Initialize stats
+        mProgInfo.reset();
+
+        // Start the programming thread
+//        mReadyToUpdate = BLOCKS_PER_CONNECTION;
+        mReadyToUpdate = 1;
+//        mReadyToUpdate = 0;
+
+        canGo = true;
+
+        Thread aaa = new Thread(new OadTask());
+        aaa.start();
+
+        mTimer = new Timer();
+        mTimerTask = new ProgTimerTask();
+        mTimer.scheduleAtFixedRate(mTimerTask, 0, TIMER_INTERVAL);
+    }
+
+    private void programBlock() {
+        if (!mProgramming) {
+            return;
+        }
+        ifBlockSend = true;
+        if (mProgInfo.iBlocks < mProgInfo.nBlocks) {
+//    if (mProgInfo.iBlocks < 100) {
+//            mProgramming = true;
+            //String msg = new String();
+
+            // Prepare block
+            mOadBuffer = new byte[OAD_BUFFER_SIZE];
+            mOadBuffer[0] = Conversion.loUint16(mProgInfo.iBlocks);
+            mOadBuffer[1] = Conversion.hiUint16(mProgInfo.iBlocks);
+            System.arraycopy(mFileBuffer, (int) mProgInfo.iBytes, mOadBuffer, 2, OAD_BLOCK_SIZE);
+            try {
+                if (((DeviceControlActivity) getActivity()).getmBluetoothLeService() != null) {
+                    if(canGo) {
+                        boolean success = ((DeviceControlActivity) getActivity()).getmBluetoothLeService().writeOTABlock(mOadBuffer);
+                        if (success) {
+//                            Log.e(TAG, String.valueOf(mProgInfo.iBlocks));
+//                            mAlreadyReadCount = mProgInfo.iBlocks + 1;
+//                            mProgInfo.iBlocks++;
+//                            mProgInfo.iBytes = mProgInfo.iBytes + OAD_BLOCK_SIZE;
+
+//                            mProgressBar.setProgress((short) ((mProgInfo.iBlocks * 100) / mProgInfo.nBlocks));
+//                        mTimeoutValue = MaxRetry;
+//                        } else {
+//                        mTimeoutValue--;
+                            ;
+                            canGo = false;
+                        }
+                    }
+                } else {
+//                    mTimeoutValue--;
+                }
+
+            } catch (NullPointerException e) {
+                //Log.e(TAG, "something wrong");
+//                mTimeoutValue--;
+                mProgramming = false;
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            isOTADone = true;
+            mProgramming = false;
+        }
+        ifBlockSend = false;
+        if (!mProgramming) {
+            try {
+                getActivity().runOnUiThread(new Runnable() {
+                    public void run() {
+                        displayStats();
+                        mButtonStopOTA.callOnClick();
+//                    stopProgramming();
+                    }
+                });
+            }catch (NullPointerException e)
+            {
+                Log.e(TAG, e.toString());
+            }
+        }
+//        if(mTimeoutValue <= 0)
+//        {
+//            Log.e(TAG, "max retry");
+//
+//            mProgramming = false;
+//            EventBus.getDefault().post(new CheckboxEvent(1));
+//        }
+    }
+
+    private void stopProgramming() {
+        if (mTimer != null) {
+            mTimer.cancel();
+            mTimer.purge();
+        }
+        if (mTimerTask != null) {
+            mTimerTask.cancel();
+        }
+        mTimerTask = null;
+        mProgramming = false;
+    }
+
+    private void displayStats() {
+        String txt;
+        int byteRate;
+        int sec = mProgInfo.iTimeElapsed / 1000;
+        if (sec > 0) {
+            byteRate = (int) (mProgInfo.iBytes / sec);
+        } else {
+            return;
+        }
+        float timeEstimate;
+        timeEstimate = ((float) (mFileImgHdr.len * 4) / (float) mProgInfo.iBytes) * sec;
+
+        txt = String.format("Time: %d / %d sec", sec, (int) timeEstimate);
+        txt += String.format("    Bytes: %d (%d/sec)", mProgInfo.iBytes, byteRate);
+        mProgressInfo.setText(txt);
+    }
+
+    private class ImgHdr {
+        long ver = -1;
+        long len = -1;
+        long rom_ver = -1;
+        //Character imgType;
+        byte[] uid = new byte[4];
+    }
+
+    private class ProgTimerTask extends TimerTask {
+        @Override
+        public void run() {
+            mProgInfo.iTimeElapsed += TIMER_INTERVAL;
+        }
+    }
+
+    private class ProgInfo {
+        long iBytes = 0; // Number of bytes programmed
+        long iBlocks = 0; // Number of blocks programmed
+        long nBlocks = 0; // Total number of blocks
+        int iTimeElapsed = 0; // Time elapsed in milliseconds
+
+        void reset() {
+            iBytes = 0;
+            iBlocks = 0;
+            iTimeElapsed = 0;
+            nBlocks = (short) (mFileImgHdr.len / (OAD_BLOCK_SIZE / HAL_FLASH_WORD_SIZE));
+            //System.out.println("nBlocks:"+nBlocks);
+        }
+    }
+
+    public void GETOTANotifyData(byte[] value) {
+        long blockReq = Conversion.buildUint16(value[1], value[0]);
+        //[chengYi | add log info get back data]
+        Log.e(TAG, "get back data blockReq: " + blockReq + ", nBlocks:" + mProgInfo.nBlocks);
+        //[chengYi | end]
+        if (((mProgInfo.nBlocks) == blockReq) && mProgramming) {
+            Log.e(TAG, "nBlock " + mProgInfo.nBlocks + " iBlock " + mProgInfo.iBlocks + "ready to stop OTA");
+            mButtonStopOTA.callOnClick();
+            //stopProgramming();
+        } else {
+            if (blockReq == 0 && !flagTag) {
+                flagTag = true;
+                mLock.lock();
+                lastBlockReq = blockReq;
+                mAlreadyReadCount = blockReq;
+                mProgInfo.iBlocks = blockReq;
+                mProgInfo.iBytes = (blockReq) * OAD_BLOCK_SIZE;
+                mLock.unlock();
+            } else {
+                mLock.lock();
+                lastBlockReq = blockReq;
+                mAlreadyReadCount = blockReq;
+                mProgInfo.iBlocks = blockReq;
+                mProgInfo.iBytes = (blockReq) * OAD_BLOCK_SIZE;
+                if(DelayTimer < 50)
+                {
+                    DelayTimer = 50;
+                }
+                mLock.unlock();
+            }
+        }
+    }
+
+    public void GETVersionData(byte[] value) {
+        StringBuilder stringBuilder = new StringBuilder(value.length);
+        stringBuilder.append(String.format("%02X", value[1]));
+        stringBuilder.append(String.format("%02X", value[0]));
+        Log.e(TAG, stringBuilder.toString());
+        mTextViewDeviceVersion.setText(stringBuilder.toString());
+
+
+        stringBuilder = new StringBuilder(value.length);
+        Log.e(TAG, String.valueOf(value.length));
+        if(value.length == 10) {
+            stringBuilder.append(String.format("%02X", value[9]));
+            stringBuilder.append(String.format("%02X", value[8]));
+        }else {
+            stringBuilder.append("FF");
+            stringBuilder.append("FF");
+        }
+        Log.e(TAG, stringBuilder.toString());
+        mTextViewDeviceRomVersion.setText(stringBuilder.toString());
+
+        MAXNotify = 10;
+    }
+
+    private boolean getFileVerion(String filepath) {
+        mFileIndexBuffer = new byte[16];
+        // Load binary file
+        try {
+            // Read the file raw into a buffer
+            InputStream stream;
+            File f = new File(filepath);
+            stream = new FileInputStream(f);
+            if(stream.available() > 16) {
+                stream.read(mFileIndexBuffer, 0, 16);
+                stream.close();
+            }else
+            {
+                stream.close();
+                return false;
+            }
+        } catch (IOException e) {
+            // Handle exceptions here
+            Log.e(TAG, e.toString());
+            return false;
+        }
+
+        if(checkBinCorrect()) {
+            StringBuilder stringBuilder = new StringBuilder(5);
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[5]));
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[4]));
+            Log.e(TAG, stringBuilder.toString());
+
+            mTextViewFileVersion.setText(stringBuilder.toString());
+
+            stringBuilder = new StringBuilder(5);
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[15]));
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[14]));
+            Log.e(TAG, stringBuilder.toString());
+
+            mTextViewOTARomVersion.setText(stringBuilder.toString());
+            return true;
+        }else
+        {
+            Toast.makeText(getContext(), "not a correct bin", Toast.LENGTH_SHORT).show();
+            return false;
+        }
+    }
+
+    private boolean getFileVerion() {
+        mFileIndexBuffer = new byte[16];
+        // Load binary file
+        try {
+            // Read the file raw into a buffer
+            InputStream stream;
+            stream = ((DeviceControlActivity)getActivity()).getContentResolver().openInputStream(mFilePath);
+            if(stream.available() > 16) {
+                stream.read(mFileIndexBuffer, 0, 16);
+                stream.close();
+            }else
+            {
+                stream.close();
+                return false;
+            }
+        } catch (IOException e) {
+            // Handle exceptions here
+            Log.e(TAG, e.toString());
+            return false;
+        }
+
+        if(checkBinCorrect()) {
+            StringBuilder stringBuilder = new StringBuilder(5);
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[5]));
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[4]));
+            Log.e(TAG, stringBuilder.toString());
+
+            mTextViewFileVersion.setText(stringBuilder.toString());
+
+            stringBuilder = new StringBuilder(5);
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[15]));
+            stringBuilder.append(String.format("%02X", mFileIndexBuffer[14]));
+            Log.e(TAG, stringBuilder.toString());
+
+            mTextViewOTARomVersion.setText(stringBuilder.toString());
+            return true;
+        }else
+        {
+            Toast.makeText(getContext(), "not a correct bin", Toast.LENGTH_SHORT).show();
+            return false;
+        }
+    }
+
+    private boolean loadFile() {
+        boolean fSuccess = false;
+        // Load binary file
+        try {
+            // Read the file raw into a buffer
+            InputStream stream;
+            stream = ((DeviceControlActivity)getActivity()).getContentResolver().openInputStream(mFilePath);
+            stream.read(mFileBuffer, 0, mFileBuffer.length);
+            stream.close();
+        } catch (IOException e) {
+            // Handle exceptions here
+            return false;
+        }
+
+        mFileImgHdr.ver = Conversion.buildUint16(mFileBuffer[5], mFileBuffer[4]);
+        mFileImgHdr.len = Conversion.buildUint16(mFileBuffer[7], mFileBuffer[6]);
+        mFileImgHdr.rom_ver = Conversion.buildUint16(mFileBuffer[15], mFileBuffer[14]);
+        //long templen = mFileImgHdr.len;
+        //templen |= 0x80000000L;
+        //mFileImgHdr.imgType = ((mFileImgHdr.ver & 1) == 1) ? 'B' : 'A';
+        System.arraycopy(mFileBuffer, 8, mFileImgHdr.uid, 0, 4);
+//        displayImageInfo(mFileImage, mFileImgHdr);
+
+        // Expected duration
+        displayStats();
+        //mTextViewFileVersion.setText(" " + String.valueOf(mFileImgHdr.ver));
+        return fSuccess;
+    }
+
+    private boolean loadFile(String filepath) {
+        boolean fSuccess = false;
+        // Load binary file
+        try {
+            // Read the file raw into a buffer
+            InputStream stream;
+            File f = new File(filepath);
+            stream = new FileInputStream(f);
+            stream.read(mFileBuffer, 0, mFileBuffer.length);
+            stream.close();
+        } catch (IOException e) {
+            // Handle exceptions here
+            return false;
+        }
+        mFileImgHdr.ver = Conversion.buildUint16(mFileBuffer[5], mFileBuffer[4]);
+        mFileImgHdr.len = Conversion.buildUint16(mFileBuffer[7], mFileBuffer[6]);
+        mFileImgHdr.rom_ver = Conversion.buildUint16(mFileBuffer[15], mFileBuffer[14]);
+        //long templen = mFileImgHdr.len;
+        //templen |= 0x80000000L;
+        //mFileImgHdr.imgType = ((mFileImgHdr.ver & 1) == 1) ? 'B' : 'A';
+        System.arraycopy(mFileBuffer, 8, mFileImgHdr.uid, 0, 4);
+//        displayImageInfo(mFileImage, mFileImgHdr);
+
+        // Expected duration
+        displayStats();
+        //mTextViewFileVersion.setText(" " + String.valueOf(mFileImgHdr.ver));
+        return fSuccess;
+    }
+
+    public void clickStopBtn() {
+        if (mProgramming) {
+            mButtonStopOTA.callOnClick();
+        }
+    }
+    public void clickRefreshBtn()
+    {
+        mButtonRefresh.callOnClick();
+    }
+
+    public boolean ismProgramming()
+    {
+        return mProgramming;
+    }
+
+    public boolean isOTADone()
+    {
+        return isOTADone;
+    }
+
+    public void setOutSideFileData(String filename, Uri selectFilePath)
+    {
+        mFilePath = selectFilePath;
+        mOTAFileAdapter.init();
+        mOTAFileAdapter.notifyDataSetChanged();
+        if(getFileVerion() /*&& filename.endsWith(".bin")*/) {
+            mTextViewFilePath.setText(filename);
+
+            if(!mButtonStartOTA.isEnabled())
+            {
+                mButtonStartOTA.setEnabled(true);
+            }
+
+        }else
+        {
+            mFilePath = null;
+            Toast.makeText(getContext(), "not a correct bin", Toast.LENGTH_SHORT).show();
+            mTextViewFileVersion.setText("");
+            mTextViewOTARomVersion.setText("");
+            mTextViewFilePath.setText("");
+
+            if(mButtonStartOTA.isEnabled())
+            {
+                mButtonStartOTA.setEnabled(false);
+            }
+
+        }
+    }
+
+    public boolean checkBinCorrect()
+    {
+        byte[] buf = new byte[4];
+        System.arraycopy(mFileIndexBuffer, 8, buf, 0, 4);
+
+        final StringBuilder stringBuilder = new StringBuilder(5);
+        stringBuilder.append(String.format("%02X ", buf[0]));
+        stringBuilder.append(String.format("%02X ", buf[1]));
+        stringBuilder.append(String.format("%02X ", buf[2]));
+        stringBuilder.append(String.format("%02X", buf[3]));
+
+        Log.e(TAG, stringBuilder.toString());
+
+        if((buf[0] == 0x42) && (buf[1] == 0x42) && (buf[2] == 0x42) && (buf[3] == 0x42))
+        {
+            OTAType = 1;
+            mButtonStartOTA.setText("Partial OTA");
+            return true;
+        }else  if((buf[0] == 0x53) && (buf[1] == 0x53) && (buf[2] == 0x53) && (buf[3] == 0x53))
+        {
+            OTAType = 2;
+            mButtonStartOTA.setText("Full OTA");
+            return true;
+        }else
+        {
+            OTAType = 0;
+            mButtonStartOTA.setText("Start OTA");
+            return false;
+        }
+    }
+
+    public void setBlockIndex(int x)
+    {
+        if(mProgramming) {
+            try {
+                if (x == 1) {
+                    mLock.lock();
+                    canGo = true;
+                    mAlreadyReadCount = mProgInfo.iBlocks + 1;
+                    mProgInfo.iBlocks++;
+                    mProgInfo.iBytes = mProgInfo.iBytes + OAD_BLOCK_SIZE;
+                    mLock.unlock();
+                    mProgressBar.setProgress((short) ((mProgInfo.iBlocks * 100) / mProgInfo.nBlocks));
+                    Log.e(TAG, String.valueOf(mProgInfo.iBlocks));
+                } else {
+                    mLock.lock();
+                    canGo = true;
+                    mLock.unlock();
+                }
+            } catch (NullPointerException e) {
+                Log.e(TAG, e.toString());
+            }
+        }
+    }
+}

+ 360 - 0
app/src/main/java/com/slam/bboxble/DeviceControlActivity.java

@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.slam.bboxble;
+
+import android.Manifest;
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.slam.bboxblelib.BluetoothLeService;
+import com.slam.bboxblelib.CheckboxEvent;
+import com.slam.bboxblelib.MainBluetooth;
+import com.slam.bboxblelib.impl.MainBluetoothImpl;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * For a given BLE device, this Activity provides the user interface to connect, display data,
+ * and display GATT services and characteristics supported by the device.  The Activity
+ * communicates with {@code BluetoothLeService}, which in turn interacts with the
+ * Bluetooth LE API.
+ */
+//public class DeviceControlActivity extends Activity implements View.OnClickListener{
+public class DeviceControlActivity extends FragmentActivity{
+    private final static String TAG = DeviceControlActivity.class.getSimpleName();
+    //[vers add]
+
+    private int mFragmentIndex = 2; //0: query 1: script 2:uuid 3: report 4: bekenTest
+    private ServiceFragment mUUIDListFragment;
+    private BekenOTAFragment mBekenOTAFragment;
+    private FrameLayout mFrameLayoutUUIDList,  mFrameLayoutBekenOTA;
+    //[vers |end]
+    public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
+    public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
+
+    private Context mContext;
+    private ImageView mImageView;
+    private String mDeviceName;
+    private String mDeviceAddress;
+    private BluetoothLeService mBluetoothLeService;
+    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
+            new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
+    private ArrayList<HashMap<String, Object>> Item = new ArrayList<HashMap<String, Object>>();
+    private HashMap<String, Integer> mNodeList = new HashMap<>();
+    private String mReportFile;
+    private int mConnected;
+    private BluetoothAdapter mBluetoothAdapter;
+    private Intent mIntent;
+
+    private Handler mHandler;
+    private Runnable mRunnable = new Runnable() {
+        @Override
+        public void run() {
+            EventBus.getDefault().post(new CheckboxEvent(2));
+        }
+    };
+
+    private int mLineNo = 1;
+    private int retryNo = 3;
+    private boolean flagDiscoverFail = false;
+    private static final int REQUEST_WRITE_STORAGE = 112;
+
+    //蓝牙接口
+    private MainBluetoothImpl mainBluetooth = new MainBluetoothImpl();
+
+    protected void makeRequest(String a) {
+        if(a.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_WRITE_STORAGE);
+        }
+    }
+
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gatt_services_characteristics);
+        mContext = this;
+
+        final Intent intent = getIntent();
+        mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
+        mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
+        Log.i(TAG,"mDeviceName:"+mDeviceName +" == "+ mDeviceAddress);
+
+        mHandler = new Handler();
+        if (Build.VERSION.SDK_INT >= 23) {
+            int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+
+            if (permission != PackageManager.PERMISSION_GRANTED) {
+                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                    AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                    builder.setMessage("Need Permission").setTitle("Permission require");
+                    builder.setPositiveButton("ok", new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            makeRequest(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+                        }
+                    });
+                    AlertDialog dialog = builder.create();
+                    dialog.show();
+                } else {
+                    makeRequest(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+                }
+            }else
+            {
+                Log.e(TAG, "nothing");
+            }
+        }
+
+        mFrameLayoutUUIDList = (FrameLayout) findViewById(R.id.framelayout_uuid);
+        mFrameLayoutBekenOTA = (FrameLayout) findViewById(R.id.framelayout_bekenOta);
+        mUUIDListFragment = (ServiceFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_uuid);
+        mBekenOTAFragment = (BekenOTAFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_bekenOta);
+        // Sets up UI references.
+        ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
+        mImageView = (ImageView) findViewById(R.id.connectionStatus);
+        mImageView.setImageResource(R.drawable.ic_bluetooth_disabled_black_48dp);
+        mFrameLayoutBekenOTA.setVisibility(View.GONE);
+
+
+        getActionBar().setTitle(mDeviceName);
+        getActionBar().setDisplayHomeAsUpEnabled(true);
+
+        final BluetoothManager bluetoothManager =
+                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+
+//        mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
+
+//        if (mBluetoothLeService != null) {
+//            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
+//            Log.e(TAG, "Connect request result =" + result);
+//        }
+
+        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+        EventBus.getDefault().register(this);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    public void onMessageEvent(CheckboxEvent event) {
+        Log.e(TAG, "**********onMessageEvent mFragmentIndex=" + mFragmentIndex);
+        Log.e(TAG, "**********onMessageEvent =" + event.getGroupPosition()+"="+event.getChildPostion()+"="+event.getIndex()+"="+event.getFlag());
+
+        if(mFragmentIndex == 2)
+        {
+            mUUIDListFragment.versTestFunction(event.getGroupPosition(), event.getChildPostion(), event.getIndex(), event.getFlag());
+        }else if(event.getmDisconnect() == 11)
+        {
+            if(mFragmentIndex == 5)
+            {
+                mBekenOTAFragment.setBlockIndex(1);
+            }
+        }else if(event.getmDisconnect() == 10)
+        {
+            if(mFragmentIndex == 5)
+            {
+                mBekenOTAFragment.setBlockIndex(2);
+            }
+        }
+        else if(event.getmDisconnect() == 1)
+        {
+            Toast.makeText(this, "Max Retry", Toast.LENGTH_SHORT).show();
+            finish();
+        }else if(event.getmDisconnect() == 2)
+        {
+            Toast.makeText(this, "Get Device Version Fail", Toast.LENGTH_SHORT).show();
+        }
+    };
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        EventBus.getDefault().unregister(this);
+
+//        mainBluetooth.onDestroy();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.action, menu);
+        if (mConnected == 2) {
+            Log.e(TAG, "mConnected == 2");
+            menu.findItem(R.id.action_connect).setVisible(false);
+            menu.findItem(R.id.action_disconnect).setVisible(true);
+            menu.findItem(R.id.connection_refresh).setActionView(null);
+        } else if (mConnected == 1) {
+            Log.e(TAG, "mConnected == 1");
+            menu.findItem(R.id.action_connect).setVisible(false);
+            menu.findItem(R.id.action_disconnect).setVisible(false);
+            menu.findItem(R.id.connection_refresh).setActionView(R.layout.actionbar_indeterminate_progress);
+        } else {
+            Log.e(TAG, "mConnected == 0");
+            menu.findItem(R.id.action_connect).setVisible(true);
+            menu.findItem(R.id.action_disconnect).setVisible(false);
+            menu.findItem(R.id.connection_refresh).setActionView(null);
+
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                //back
+                if (mFragmentIndex == 5) {
+                } else
+                {
+                    mIntent = new Intent();
+                    mIntent.putExtra("Result OTA", "Exit OTA by user");
+                    DeviceControlActivity.this.setResult(4, mIntent);
+                    onBackPressed();
+                }
+                break;
+            default:
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private void updateConnectionState(final int resourceId) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                if(resourceId == R.string.connected)
+                {
+                    mImageView.setImageResource(R.drawable.ic_bluetooth_connected_black_48dp);
+                }else
+                {
+                    mImageView.setImageResource(R.drawable.ic_bluetooth_disabled_black_48dp);
+                }
+            }
+        });
+    }
+
+
+
+    public void changeFragment(int index)
+    {
+        if(index == 2)
+        {
+            mFragmentIndex = 2;
+            mFrameLayoutUUIDList.setVisibility(View.VISIBLE);
+            mFrameLayoutBekenOTA.setVisibility(View.GONE);
+        }else if(index == 4)
+        {
+            mFragmentIndex = 4;
+            mFrameLayoutUUIDList.setVisibility(View.GONE);
+            mFrameLayoutBekenOTA.setVisibility(View.GONE);
+        }else if(index == 5)
+        {
+            mFragmentIndex = 5;
+            mFrameLayoutUUIDList.setVisibility(View.GONE);
+            mFrameLayoutBekenOTA.setVisibility(View.VISIBLE);
+        }
+
+    }
+
+    public int getConnectStatus()
+    {
+        return mConnected;
+    }
+
+    public BluetoothLeService getmBluetoothLeService()
+    {
+        return mBluetoothLeService;
+    }
+
+    public void clearItem()
+    {
+        Item.clear();
+    }
+
+
+
+
+    public void pushOTAFragmentRefreshBtn()
+    {
+        mBekenOTAFragment.clickRefreshBtn();
+    }
+
+    public void letGetVersionTrigger()
+    {
+        mHandler.removeCallbacks(mRunnable);
+        mHandler.postDelayed(mRunnable, 5000);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+
+        if(requestCode == 2 && resultCode == Activity.RESULT_OK)
+        {
+            Uri selectedMediaUri = data.getData();
+
+            File f = new File(""+selectedMediaUri);
+            Log.e(TAG, selectedMediaUri.getPath());
+            mBekenOTAFragment.setOutSideFileData(f.getName(), selectedMediaUri);
+        }
+    }
+
+    public void ByeByeFunction()
+    {
+        mIntent = new Intent();
+        mIntent.putExtra("Result OTA", "Max Retry for get device Version");
+        DeviceControlActivity.this.setResult(4, mIntent);
+        finish();
+    }
+}

+ 442 - 0
app/src/main/java/com/slam/bboxble/DeviceScanActivity.java

@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.slam.bboxble;
+
+import android.Manifest;
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.slam.bboxblelib.DeviceEvent;
+import com.slam.bboxblelib.MainBluetooth;
+import com.slam.bboxblelib.impl.MainBluetoothImpl;
+import com.slam.bboxblelib.Responser;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * Activity for scanning and displaying available Bluetooth LE devices.
+ */
+public class DeviceScanActivity extends Activity implements View.OnClickListener {
+
+    private final String TAG = "DeviceScanActivity";
+    private LeDeviceListAdapter mLeDeviceListAdapter;
+    private LeDeviceListAdapter mPairLeDeviceListAdapter;
+    private BluetoothAdapter mBluetoothAdapter;
+    private boolean mScanning;
+    private ListView mListView, mPairListView;
+    private Button mButtonStopScan, mButtonStartScan;
+    private TextView mTextViewResult;
+    private boolean noNeedShowDialog = false;
+
+    private static final int REQUEST_ENABLE_BT = 1;
+    private static final int REQUEST_WRITE_STORAGE = 112;
+
+    //蓝牙
+    private MainBluetoothImpl mainBluetooth = new MainBluetoothImpl();
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+        switch (requestCode) {
+            case REQUEST_WRITE_STORAGE:
+                FileUnit.getOTAFilePath();
+                break;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+
+        getActionBar().setTitle(R.string.title_devices);
+        setContentView(R.layout.list_device_view);
+
+        if (Build.VERSION.SDK_INT >= 23) {
+            int permission1 = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+            int permission2 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
+            if (permission1 != PackageManager.PERMISSION_GRANTED || permission2 != PackageManager.PERMISSION_GRANTED) {
+                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
+
+                    ActivityCompat.requestPermissions(DeviceScanActivity.this,
+                            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                            REQUEST_WRITE_STORAGE);
+                } else {
+                    ActivityCompat.requestPermissions(DeviceScanActivity.this,
+                            new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                            REQUEST_WRITE_STORAGE);
+                }
+            }
+        } else {
+            FileUnit.getOTAFilePath();
+        }
+
+        mButtonStartScan = (Button) findViewById(R.id.button_startScan);
+        mButtonStopScan = (Button) findViewById(R.id.button_stopScan);
+
+        mButtonStartScan.setOnClickListener(this);
+        mButtonStopScan.setOnClickListener(this);
+
+        mButtonStopScan.setVisibility(View.GONE);
+
+        mTextViewResult = (TextView) findViewById(R.id.textview_OTAResult);
+        mListView = (ListView) findViewById(R.id.list_device);
+        mPairListView = (ListView) findViewById(R.id.list_pair_device);
+
+        mPairListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final BluetoothDevice device = mPairLeDeviceListAdapter.getDevice(position);
+                if (device == null) return;
+
+                final Intent intent = new Intent(DeviceScanActivity.this, DeviceControlActivity.class);
+                intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
+                intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
+                mScanning = false;
+                //蓝牙部分
+                mainBluetooth.stopScanLeDevice();
+                noNeedShowDialog = false;
+                startActivityForResult(intent, 2);
+            }
+        });
+
+        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
+                final BluetoothDevice device = mLeDeviceListAdapter.getDevice(i);
+                if (device == null) return;
+                final Intent intent = new Intent(DeviceScanActivity.this, DeviceControlActivity.class);
+                intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
+                intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
+                mScanning = false;
+                //蓝牙部分
+                mainBluetooth.stopScanLeDevice();
+                noNeedShowDialog = false;
+                startActivityForResult(intent, 2);
+            }
+        });
+        // Use this check to determine whether BLE is supported on the device.  Then you can
+        // selectively disable BLE-related features.
+        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
+            Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
+            finish();
+        }
+        // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
+        // BluetoothAdapter through BluetoothManager.
+        final BluetoothManager bluetoothManager =
+                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+        mBluetoothAdapter = bluetoothManager.getAdapter();
+
+        //初始化蓝牙参数部分
+        Responser responser = new Responser() {
+            @Override
+            public void onSuccess(DeviceEvent deviceEvent) {
+                if (deviceEvent.getType().equals("pairedDevices")) {
+                    if (deviceEvent.getDevices().size() > 0) {
+                        for (BluetoothDevice device : deviceEvent.getDevices()) {
+                            Log.e(TAG, "**********DeviceEvent responser=" + device.getAddress() + device.getName());
+                            mPairLeDeviceListAdapter.addDevice(device);
+                            mPairLeDeviceListAdapter.notifyDataSetChanged();
+                        }
+                        mScanning = true;
+                    }
+                } else if (deviceEvent.getType().equals("device")) {
+//                        Log.e(TAG, "**********DeviceEvent responser=" + deviceEvent.getDevice().getAddress());
+//                        Log.e(TAG, "**********DeviceEvent responser=" + deviceEvent.getRssi());
+                    if (deviceEvent.getDevice().getBondState() != BluetoothDevice.BOND_BONDED) {
+                        mLeDeviceListAdapter.addDevice(deviceEvent.getDevice());
+                        mLeDeviceListAdapter.notifyDataSetChanged();
+                    }
+                    ;
+                } else if (deviceEvent.getType().equals("none")) {
+                    runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            mButtonStopScan.performClick();
+                        }
+                    });
+                }
+
+            }
+
+            @Override
+            public void onFailed(String prompt) {
+
+            }
+
+//                    @Override
+//                    public void onSuccessDevices(Set<BluetoothDevice> devices) {
+//                        if (devices.size() > 0) {
+//                            for (BluetoothDevice device : devices) {
+//                                Log.e(TAG, "**********DeviceEvent responser=" +device.getAddress() + device.getName() );
+//                                mPairLeDeviceListAdapter.addDevice(device);
+//                                mPairLeDeviceListAdapter.notifyDataSetChanged();
+//                            }
+//                            mScanning = true;
+//                        }
+//
+//                    }
+//
+//                    @Override
+//                    public void onSuccess(String data) {
+//                        runOnUiThread(new Runnable() {
+//                            @Override
+//                            public void run() {
+//                                mButtonStopScan.performClick();
+//                            }
+//                        });
+//                    }
+        };
+
+        mainBluetooth.onCreate(this,responser);
+
+        // Checks if Bluetooth is supported on the device.
+        if (mBluetoothAdapter == null) {
+            Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
+            finish();
+            return;
+        }
+
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.main, menu);
+        if (!mScanning) {
+            menu.findItem(R.id.menu_stop).setVisible(false);
+            menu.findItem(R.id.menu_scan).setVisible(true);
+            menu.findItem(R.id.menu_refresh).setActionView(null);
+            mButtonStopScan.setVisibility(View.GONE);
+            mButtonStartScan.setVisibility(View.VISIBLE);
+        } else {
+            menu.findItem(R.id.menu_stop).setVisible(true);
+            menu.findItem(R.id.menu_scan).setVisible(false);
+            menu.findItem(R.id.menu_refresh).setActionView(
+                    R.layout.actionbar_indeterminate_progress);
+            mButtonStopScan.setVisibility(View.VISIBLE);
+            mButtonStartScan.setVisibility(View.GONE);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        return true;
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
+        // fire an intent to display a dialog asking the user to grant permission to enable it.
+        Log.e(TAG, "onResume");
+        if (!noNeedShowDialog) {
+            if (!mBluetoothAdapter.isEnabled()) {
+                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
+            }
+        }
+
+        mLeDeviceListAdapter = new LeDeviceListAdapter();
+        mPairLeDeviceListAdapter = new LeDeviceListAdapter();
+        mListView.setAdapter(mLeDeviceListAdapter);
+        mPairListView.setAdapter(mPairLeDeviceListAdapter);
+
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        // User chose not to enable Bluetooth.
+        Log.e(TAG, "back check resultCode: " + resultCode);
+        if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
+            finish();
+            return;
+        } else if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_OK) {
+            Toast.makeText(this, "Bluetooth Enable", Toast.LENGTH_SHORT).show();
+        } else if (requestCode == 2) {
+            if (resultCode == 4 || resultCode == 3) {
+                noNeedShowDialog = true;
+                String aaa = data.getExtras().getString("Result OTA");
+                mTextViewResult.setText(aaa);
+            } else if (resultCode == 5) {
+                noNeedShowDialog = false;
+                Toast.makeText(this, "OTA Done", Toast.LENGTH_SHORT).show();
+                mTextViewResult.setText("");
+            } else {
+                noNeedShowDialog = false;
+                mTextViewResult.setText("");
+            }
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (mButtonStartScan.getVisibility() == View.GONE) {
+            mButtonStopScan.performClick();
+        }
+        mLeDeviceListAdapter.clear();
+        mPairLeDeviceListAdapter.clear();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+
+    @Override
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.button_startScan:
+                mLeDeviceListAdapter.clear();
+                mPairLeDeviceListAdapter.clear();
+                mButtonStopScan.setVisibility(View.VISIBLE);
+                mButtonStartScan.setVisibility(View.GONE);
+                mainBluetooth.startScanLeDevice();
+                invalidateOptionsMenu();
+                break;
+            case R.id.button_stopScan:
+                mButtonStopScan.setVisibility(View.GONE);
+                mButtonStartScan.setVisibility(View.VISIBLE);
+                mainBluetooth.stopScanLeDevice();
+                break;
+            default:
+                break;
+        }
+    }
+
+    // Adapter for holding devices found through scanning.
+    private class LeDeviceListAdapter extends BaseAdapter {
+        private ArrayList<BluetoothDevice> mLeDevices;
+        private LayoutInflater mInflator;
+
+        public LeDeviceListAdapter() {
+            super();
+            mLeDevices = new ArrayList<BluetoothDevice>();
+            mInflator = DeviceScanActivity.this.getLayoutInflater();
+        }
+
+        public void addDevice(BluetoothDevice device) {
+            if (!mLeDevices.contains(device)) {
+                mLeDevices.add(device);
+            }
+        }
+
+        public BluetoothDevice getDevice(int position) {
+            if (mLeDevices.size() > position) {
+                return mLeDevices.get(position);
+            } else {
+                return null;
+            }
+        }
+
+        public void clear() {
+            mLeDevices.clear();
+        }
+
+        @Override
+        public int getCount() {
+            return mLeDevices.size();
+        }
+
+        @Override
+        public Object getItem(int i) {
+            return mLeDevices.get(i);
+        }
+
+        @Override
+        public long getItemId(int i) {
+            return i;
+        }
+
+        @Override
+        public View getView(int i, View view, ViewGroup viewGroup) {
+            ViewHolder viewHolder;
+            // General ListView optimization code.
+            if (view == null) {
+                view = mInflator.inflate(R.layout.listitem_device, null);
+                viewHolder = new ViewHolder();
+                viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address);
+                viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
+                view.setTag(viewHolder);
+            } else {
+                viewHolder = (ViewHolder) view.getTag();
+            }
+
+            BluetoothDevice device = mLeDevices.get(i);
+            final String deviceName = device.getName();
+            if (deviceName != null && deviceName.length() > 0)
+                viewHolder.deviceName.setText(deviceName);
+            else
+                viewHolder.deviceName.setText(R.string.unknown_device);
+            viewHolder.deviceAddress.setText(device.getAddress());
+
+            return view;
+        }
+    }
+
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean("HBG", noNeedShowDialog);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        noNeedShowDialog = savedInstanceState.getBoolean("HBG");
+    }
+
+    static class ViewHolder {
+        TextView deviceName;
+        TextView deviceAddress;
+    }
+}

+ 36 - 0
app/src/main/java/com/slam/bboxble/FileInfo.java

@@ -0,0 +1,36 @@
+package com.slam.bboxble;
+
+/**
+ * Created by vers on 2016/12/12.
+ */
+
+public class FileInfo {
+    private String mPath, mFileName;
+    private boolean isCheck;
+
+    public FileInfo(String path, String filename) {
+        mPath = path;
+        mFileName = filename;
+    }
+
+    public String getPath()
+    {
+        return mPath;
+    }
+
+    public void setChecked(boolean flag)
+    {
+        isCheck = flag;
+    }
+
+    public boolean getIsCheck()
+    {
+        return isCheck;
+    }
+
+    public String getFileName()
+    {
+        return mFileName;
+    }
+
+}

+ 59 - 0
app/src/main/java/com/slam/bboxble/FileUnit.java

@@ -0,0 +1,59 @@
+package com.slam.bboxble;
+
+import android.os.Environment;
+
+import java.io.File;
+
+/**
+ * Created by vers on 12/5/16.
+ */
+
+public class FileUnit {
+
+    public static final String TAG = "FileUnit";
+
+    public static String getScriptFilePath()
+    {
+        File localFile = new File(getFilePath() + "/script");
+        if (!localFile.exists()) {
+            localFile.mkdir();
+        }
+        return getFilePath() + "/script";
+    }
+
+    public static String getReportFilePath()
+    {
+        File localFile = new File(getFilePath() + "/report");
+        if (!localFile.exists()) {
+            localFile.mkdir();
+        }
+        return getFilePath() + "/report";
+    }
+
+    public static String getOTAFilePath()
+    {
+        File localFile = new File(getSDPath() + "/Download");
+        if (!localFile.exists()) {
+            boolean aaa = localFile.mkdir();
+        }
+        return getSDPath() + "/Download";
+    }
+
+    private static String getFilePath() {
+        File localFile = new File(getSDPath() + "/BLEMesh");
+        if (!localFile.exists()) {
+            localFile.mkdir();
+        }
+        return getSDPath() + "/BLEMesh";
+    }
+
+    public static String getSDPath() {
+        if (Environment.getExternalStorageState().equals("mounted")) {
+            return Environment.getExternalStorageDirectory().toString();
+        }
+        else
+        {
+            return Environment.getDownloadCacheDirectory().toString();
+        }
+    }
+}

+ 91 - 0
app/src/main/java/com/slam/bboxble/OTAFileAdapter.java

@@ -0,0 +1,91 @@
+package com.slam.bboxble;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.CheckBox;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Created by lenovo on 2017/9/27.
+ */
+
+public class OTAFileAdapter extends BaseAdapter {
+
+    private final String TAG = OTAFileAdapter.class.getSimpleName();
+    private Context mContext;
+    private LayoutInflater mInflater;
+
+    public static HashMap<Integer, Boolean> isSelected;
+    private HashMap<String, FileInfo> mOTAFileList = null;
+    private ArrayList<String> mFileList = null;
+
+    public OTAFileAdapter(Context context, HashMap<String, FileInfo> list,
+                          int resource, ArrayList<String> arrayList) {
+        mContext = context;
+        mOTAFileList = list;
+        mFileList = arrayList;
+        mInflater = LayoutInflater.from(context);
+        init();
+    }
+
+    public void init() {
+        isSelected = new HashMap<Integer, Boolean>();
+        for (int i = 0; i < mOTAFileList.size(); i++) {
+            isSelected.put(i, false);
+        }
+    }
+
+    @Override
+    public int getCount() {
+        return mOTAFileList.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return mOTAFileList.get(mFileList.get(position).toString());
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        CheckBox mCheckBox;
+        if(convertView != null)
+        {
+            mCheckBox = (CheckBox) convertView.getTag();
+        }else
+        {
+            convertView = mInflater.inflate(R.layout.listitem_script, null);
+            mCheckBox = (CheckBox) convertView.findViewById(R.id.script_item);
+            convertView.setTag(mCheckBox);
+        }
+
+        Log.i(TAG, mFileList.get(position));
+        mCheckBox.setText(mOTAFileList.get(mFileList.get(position)).getFileName());
+        mCheckBox.setChecked(isSelected.get(position));
+
+        return convertView;
+    }
+
+    public String getCheckedFileName()
+    {
+        for(int forCount = 0; forCount < mOTAFileList.size(); forCount++)
+        {
+            if(isSelected.get(forCount))
+            {
+                String lFileName = mFileList.get(forCount).toString();
+                return lFileName;
+            }
+        }
+        return null;
+    }
+}

+ 321 - 0
app/src/main/java/com/slam/bboxble/ServiceFragment.java

@@ -0,0 +1,321 @@
+package com.slam.bboxble;
+
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ExpandableListView;
+import android.widget.SimpleExpandableListAdapter;
+import android.widget.Toast;
+
+import com.slam.bboxblelib.Conversion;
+import com.slam.bboxblelib.GattAttributes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by vers on 2016/12/19.
+ */
+
+public class ServiceFragment extends Fragment implements View.OnClickListener {
+
+    private String TAG = "ServiceFragment";
+    private Button mButtonUUID, mButtonOTA;
+    private Button mButtonSend;
+    private ExpandableListView mGattServicesList;
+    private UUID uuida =     UUID.fromString(GattAttributes.uuid_identification_code);
+    //ota 下面的两个特征值
+    private UUID uuid_ota1 = UUID.fromString(GattAttributes.uuid_ota1);
+    private UUID uuid_ota2 = UUID.fromString(GattAttributes.uuid_ota2);
+    private int canOTAcount = 0;
+    private final String LIST_NAME = "NAME";
+    private final String LIST_UUID = "UUID";
+    private final String LIST_ABLITY = "TYPE";
+    private final String LIST_Value = "VALUE";
+    private UUIDAdapter_2 gattServiceAdapter;
+    private List<List<Boolean>> mWriteList = new ArrayList<>();
+    private List<List<Boolean>> mNotifyList = new ArrayList<>();
+    private List<List<Boolean>> mIndicateList = new ArrayList<>();
+    private BluetoothGattCharacteristic mNotifyCharacteristic = null;
+    private BluetoothGattCharacteristic mIndicateCharacteristic = null;
+    private BluetoothGattCharacteristic mOTAUUID1 = null;
+    private BluetoothGattCharacteristic mOTAUUID2 = null;
+    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
+            new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
+
+    public void setOTAUUID1(BluetoothGattCharacteristic a)
+    {
+        mOTAUUID1 = a;
+    }
+    public void setOTAUUID2(BluetoothGattCharacteristic a)
+    {
+        mOTAUUID2 = a;
+    }
+
+    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+        Log.e(TAG, "Service Fragment onCreateView");
+        View view = inflater.inflate(R.layout.fragment_srivce, container, false);
+
+        mButtonUUID = (Button) view.findViewById(R.id.button_uuidToUUID);
+        mButtonOTA = (Button) view.findViewById(R.id.button_uuidToOTA);
+//        button_send
+        mButtonSend = (Button) view.findViewById(R.id.button_send);
+        mGattServicesList = (ExpandableListView) view.findViewById(R.id.gatt_services_list);
+        mGattServicesList.setOnChildClickListener(servicesListClickListner);
+        mButtonUUID.setOnClickListener(this);
+        mButtonOTA.setOnClickListener(this);
+        mButtonSend.setOnClickListener(this);
+        mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
+        return view;
+    }
+
+    @Override
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+    }
+    private final ExpandableListView.OnChildClickListener servicesListClickListner = new ExpandableListView.OnChildClickListener() {
+        @Override
+        public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
+            if (mGattCharacteristics != null)
+            {
+                final BluetoothGattCharacteristic characteristic =
+                                mGattCharacteristics.get(groupPosition).get(childPosition);
+                final int charaProp = characteristic.getProperties();
+
+                Log.i(TAG,"ExpandableListView.OnChildClickListener=="+charaProp);
+                if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) == 8)
+                {
+                    ((DeviceControlActivity)getActivity()).getmBluetoothLeService().setServiceandCharacteristic(characteristic.getService().getUuid(), characteristic.getUuid(), 1);
+                }
+                else if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 4)
+                {
+                    ((DeviceControlActivity)getActivity()).getmBluetoothLeService().setServiceandCharacteristic(characteristic.getService().getUuid(), characteristic.getUuid(), 0);
+
+                }
+            }
+            return true;
+        }
+    };
+
+    public void versTestFunction(int groupPosition, int childPosition, int index, boolean flag)
+    {
+        Log.e(TAG, String.valueOf(groupPosition) + " " + String.valueOf(childPosition) + " " + String.valueOf(index));
+        if (mGattCharacteristics != null) {
+            final BluetoothGattCharacteristic characteristic =
+                    mGattCharacteristics.get(groupPosition).get(childPosition);
+            final int charaProp = characteristic.getProperties();
+
+            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 16 && index == 2) {
+                mNotifyCharacteristic = characteristic;
+                    if (mNotifyList.get(groupPosition).get(childPosition) == false && flag == true) {
+                        if (((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicNotification(characteristic, true)) {
+                            mNotifyList.get(groupPosition).set(childPosition, true);
+                            ((DeviceControlActivity) getActivity()).getmBluetoothLeService().readDescriptor(characteristic.getDescriptor(uuida));
+                        } else {
+                            ;
+                        }
+                    } else if (mNotifyList.get(groupPosition).get(childPosition) == true && flag == false) {
+                        ((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicNotification(characteristic, false);
+                        mNotifyList.get(groupPosition).set(childPosition, false);
+                    } else ;
+                }
+
+                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) == 32 && index == 3) {
+                    mNotifyCharacteristic = characteristic;
+                        if (mIndicateList.get(groupPosition).get(childPosition) == false && flag == true) {
+                            if (((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicIndication(
+                                    characteristic, true)) {
+                                mIndicateList.get(groupPosition).set(childPosition, true);
+                            }
+                        } else if (mIndicateList.get(groupPosition).get(childPosition) == true && flag == false) {
+                            mIndicateList.get(groupPosition).set(childPosition, false);
+                            ((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicIndication(characteristic, flag);
+                        }
+                    }
+                }
+                gattServiceAdapter.notifyDataSetChanged();
+    }
+
+
+    ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
+    ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();
+    ArrayList<UUIDCheckList> checkLists = new ArrayList<UUIDCheckList>();
+    public void displayGattServices(List<BluetoothGattService> gattServices) {
+        int charSize = 0;
+        Log.e(TAG, "****************displayGattServices");
+        canOTAcount = 0;
+        mOTAUUID1 = null;
+        mOTAUUID2 = null;
+        if (gattServices == null) {
+            Log.e(TAG, "gattService is null");
+            return;
+        }
+        clearUUIDList();
+        String uuid = null;
+        String unknownServiceString = getResources().getString(R.string.unknown_service);
+        String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
+        mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
+//         Loops through available GATT Services.
+        for (BluetoothGattService gattService : gattServices) {
+            HashMap<String, String> currentServiceData = new HashMap<String, String>();
+            int tempCharSize = 0;
+            uuid = gattService.getUuid().toString();
+            currentServiceData.put(
+                    LIST_NAME, GattAttributes.lookup(uuid, unknownServiceString));
+            currentServiceData.put(LIST_UUID, uuid);
+
+            if (!gattServiceData.contains(currentServiceData)) {
+
+                gattServiceData.add(currentServiceData);
+//
+                ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
+                        new ArrayList<HashMap<String, String>>();
+                List<BluetoothGattCharacteristic> gattCharacteristics =
+                        gattService.getCharacteristics();
+                ArrayList<BluetoothGattCharacteristic> charas =
+                        new ArrayList<BluetoothGattCharacteristic>();
+                List<Boolean> serviceList_1 = new ArrayList<>();
+                List<Boolean> serviceList_2 = new ArrayList<>();
+                List<Boolean> serviceList_3 = new ArrayList<>();
+
+//             Loops through available Characteristics.
+                for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
+                    serviceList_1.add(false);
+                    serviceList_2.add(false);
+                    serviceList_3.add(false);
+                    UUIDCheckList lUUIDCheckList = new UUIDCheckList();
+                    tempCharSize++;
+                    charas.add(gattCharacteristic);
+                    HashMap<String, String> currentCharaData = new HashMap<String, String>();
+                    uuid = gattCharacteristic.getUuid().toString();
+                    if(uuid.equals(uuid_ota1.toString()))
+                    {
+                        canOTAcount = canOTAcount + 1;
+                        mOTAUUID1 = gattCharacteristic;
+                        Log.e(TAG, "find one");
+                        ((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicNotification(mOTAUUID1, true);
+                    }else if(uuid.equals(uuid_ota2.toString()))
+                    {
+                        canOTAcount = canOTAcount + 1;
+                        mOTAUUID2 = gattCharacteristic;
+                        Log.e(TAG, "find two");
+                    }
+                    final int charaProp = gattCharacteristic.getProperties();
+                    StringBuilder a = new StringBuilder(" ");
+                    currentCharaData.put(LIST_NAME, GattAttributes.lookup(uuid, unknownCharaString));
+                    currentCharaData.put(LIST_UUID, uuid);
+                    if((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) == 2)
+                    {
+                        a.append("[Read] ");
+                    }
+                    if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 4)
+                    {
+                        lUUIDCheckList.setWriteFlag(true);
+                        a.append("[Write No Response] ");
+                    }
+                    if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE)== 8)
+                    {
+                        lUUIDCheckList.setWriteFlag(true);
+                        a.append("[Write] ");
+                    }
+                    if((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 16)
+                    {
+                        lUUIDCheckList.setNotifyFlag(true);
+                        a.append("[Notify] ");
+                    }
+                    if((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) == 32)
+                    {
+                        lUUIDCheckList.setIndicateFlag(true);
+                        a.append("[Indicate] ");
+                    }
+                    currentCharaData.put(LIST_ABLITY, a.toString());
+                    if (!gattCharacteristicGroupData.contains(currentCharaData)) {
+                        gattCharacteristicGroupData.add(currentCharaData);
+                        checkLists.add(lUUIDCheckList);
+                    }
+                }
+                if (tempCharSize > charSize) charSize = tempCharSize;
+                mWriteList.add(serviceList_1);
+                mNotifyList.add(serviceList_2);
+                mIndicateList.add(serviceList_3);
+                mGattCharacteristics.add(charas);
+                gattCharacteristicData.add(gattCharacteristicGroupData);
+            }
+        }
+
+        if(canOTAcount == 2)
+        {
+            Log.e(TAG, "can update OTA");
+
+        }
+
+        gattServiceAdapter = new UUIDAdapter_2(getContext(), gattServiceData, gattCharacteristicData, mWriteList, mNotifyList, mIndicateList, checkLists);
+
+        mGattServicesList.setAdapter(gattServiceAdapter);
+    }
+
+    public void clearUUIDList() {
+        mGattServicesList.setAdapter((UUIDAdapter_2) null);
+    }
+
+    @Override
+    public void onClick(View view) {
+        switch (view.getId()) {
+            case R.id.button_uuidToUUID:
+                break;
+            case R.id.button_uuidToOTA:
+                if(canChangeToOTA())
+                {
+                        ((DeviceControlActivity) getActivity()).pushOTAFragmentRefreshBtn();
+                        boolean bbb = ((DeviceControlActivity) getActivity()).getmBluetoothLeService().setCharacteristicNotification(mOTAUUID2, true);
+                        if(bbb) {
+                            ((DeviceControlActivity) getActivity()).changeFragment(5);
+                        }else
+                            Toast.makeText(getContext(), "Enable notify false", Toast.LENGTH_SHORT).show();
+
+                }else
+                {
+                    Toast.makeText(getContext(), "Not Support OTA Function", Toast.LENGTH_SHORT).show();
+                }
+                break;
+            case R.id.button_send:
+                Log.e(TAG, "button_send");
+                String str = Conversion.str2HexStr("V");
+                Log.i(TAG,str);
+                byte[] result = Conversion.hexStringToBytes(str);
+                UUID service =UUID.fromString("0000FFF0-0000-1000-8000-00805F9B34FB");
+                UUID characteristic =UUID.fromString("0000FFF2-0000-1000-8000-00805F9B34FB");
+                int mode = 0;
+                ((DeviceControlActivity)getActivity()).getmBluetoothLeService().setServiceandCharacteristic(service,characteristic,mode);
+                ((DeviceControlActivity)getActivity()).getmBluetoothLeService().writeBLECharacteristicValue(result);
+                break;
+            default:
+                break;
+        }
+    }
+    private boolean canChangeToOTA()
+    {
+        if(canOTAcount == 2)
+            return true;
+        else
+            return false;
+    }
+
+    public BluetoothGattCharacteristic getmOTAUUID1()
+    {
+        if(mOTAUUID1 != null)
+        {
+            return mOTAUUID1;
+        }else
+            return null;
+    }
+}

+ 218 - 0
app/src/main/java/com/slam/bboxble/UUIDAdapter_2.java

@@ -0,0 +1,218 @@
+package com.slam.bboxble;
+
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import com.slam.bboxblelib.CheckboxEvent;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Created by vers on 2017/8/1.
+ */
+
+public class UUIDAdapter_2 extends BaseExpandableListAdapter {
+
+
+    private static final String LIST_NAME = "NAME";
+    private static final String LIST_UUID = "UUID";
+    private static final String LIST_ABLITY = "TYPE";
+
+    private List<List<Boolean>> NotifyArray;
+    private List<List<Boolean>> IndicateArray;
+    private List<List<Boolean>> WriteArray;
+
+    private static final String TAG = UUIDAdapter_2.class.getSimpleName();
+    private Context mContext;
+    private ArrayList<HashMap<String, String>> mListParentData = new ArrayList<HashMap<String, String>>();
+    private ArrayList<ArrayList<HashMap<String, String>>> mListChildData = new ArrayList<ArrayList<HashMap<String, String>>>();
+    ArrayList<UUIDCheckList> mCheckLists = new ArrayList<UUIDCheckList>();
+
+    public UUIDAdapter_2(Context context, ArrayList<HashMap<String, String>> gattServiceData,
+                         ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData,
+                         List<List<Boolean>> writeArray , List<List<Boolean>> mNotify,
+                         List<List<Boolean>> indicate, ArrayList<UUIDCheckList> arrayList)
+    {
+        mContext = context;
+        mListParentData = gattServiceData;
+        mListChildData = gattCharacteristicData;
+        WriteArray = writeArray;
+        NotifyArray = mNotify;
+        IndicateArray = indicate;
+        mCheckLists = arrayList;
+    }
+
+    @Override
+    public int getGroupCount() {
+        if(mListParentData != null) {
+            return mListParentData.size();
+        }
+        else {
+            return 0;
+        }
+    }
+
+    @Override
+    public int getChildrenCount(int groupPosition) {
+        return mListChildData.get(mListParentData.indexOf(mListParentData.get(groupPosition))).size();
+    }
+
+    @Override
+    public Object getGroup(int groupPosition) {
+        return mListParentData.get(groupPosition);
+    }
+
+    @Override
+    public Object getChild(int groupPosition, int childPosition) {
+        return mListChildData.get(mListParentData.indexOf(mListParentData.get(groupPosition))).get(childPosition);
+    }
+
+    @Override
+    public long getGroupId(int groupPosition) {
+
+        return groupPosition;
+    }
+
+    @Override
+    public long getChildId(int groupPosition, int childPosition) {
+        return childPosition;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return false;
+    }
+
+    @Override
+    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
+        View view = convertView;
+        if(view == null)
+        {
+            view = LayoutInflater.from(mContext).inflate(android.R.layout.simple_expandable_list_item_2, null);
+            GroupViewHolder holder = new GroupViewHolder(view);
+            view.setTag(holder);
+        }
+        GroupViewHolder holder = (GroupViewHolder) view.getTag();
+
+        holder.list_name.setText(((HashMap<String, String>)getGroup(groupPosition)).get(LIST_NAME));
+        holder.list_uuid.setText(((HashMap<String, String>)getGroup(groupPosition)).get(LIST_UUID));
+        return view;
+    }
+
+    @Override
+    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
+        View view = convertView;
+
+        if(view == null)
+        {
+            view = LayoutInflater.from(mContext).inflate(R.layout.listitem_uuid, null);
+            ChildViewHolder holder = new ChildViewHolder(view);
+            view.setTag(holder);
+        }
+
+        ChildViewHolder holder = (ChildViewHolder) view.getTag();
+
+        holder.list_name.setText(((HashMap<String, String>)getChild(groupPosition, childPosition)).get(LIST_NAME));
+        holder.list_uuid.setText(((HashMap<String, String>)getChild(groupPosition, childPosition)).get(LIST_UUID));
+        holder.list_ablity.setText(((HashMap<String, String>)getChild(groupPosition, childPosition)).get(LIST_ABLITY));
+
+
+//        holder.uuidCheckbox.setChecked(WriteArray.get(groupPosition).get(childPosition));
+        holder.notifyCheckbox.setChecked(NotifyArray.get(groupPosition).get(childPosition));
+        holder.indicateCheckbox.setChecked(IndicateArray.get(groupPosition).get(childPosition));
+
+//        holder.uuidCheckbox.setChecked(WriteArray[groupPosition][childPosition]);
+//        holder.notifyCheckbox.setChecked(NotifyArray[groupPosition][childPosition]);
+//        holder.indicateCheckbox.setChecked(IndicateArray[groupPosition][childPosition]);
+
+//        holder.uuidCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+//            @Override
+//            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+//                Log.e(TAG, String.valueOf(groupPosition) + " " + String.valueOf(childPosition) +" 1 " +String.valueOf(isChecked));
+//                EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 1, isChecked));
+//            }
+//        });
+
+        holder.notifyCheckbox.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if(!NotifyArray.get(groupPosition).get(childPosition)) {
+                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 2, true));
+                }else
+                {
+                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 2, false));
+                }
+            }
+        });
+
+        holder.indicateCheckbox.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if(!IndicateArray.get(groupPosition).get(childPosition)) {
+                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 3, true));
+                }else
+                {
+                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 3, false));
+                }
+            }
+        });
+//        holder.notifyCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+//            @Override
+//            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+//                Log.e(TAG, String.valueOf(groupPosition) + " " + String.valueOf(childPosition) +" 2 " +String.valueOf(isChecked));
+//                if(isChecked) {
+//                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 2, isChecked));
+//                }
+//            }
+//        });
+//
+//        holder.indicateCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+//            @Override
+//            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+//                Log.e(TAG, String.valueOf(groupPosition) + " " + String.valueOf(childPosition) +" 3 " +String.valueOf(isChecked));
+//                if(isChecked) {
+//                    EventBus.getDefault().post(new CheckboxEvent(groupPosition, childPosition, 3, isChecked));
+//                }
+//            }
+//        });
+        return view;
+    }
+
+    @Override
+    public boolean isChildSelectable(int groupPosition, int childPosition) {
+        return true;
+    }
+
+    static class GroupViewHolder {
+        TextView list_name, list_uuid;
+        public GroupViewHolder(View view) {
+            list_name = (TextView) view.findViewById(android.R.id.text1);
+            list_uuid = (TextView) view.findViewById(android.R.id.text2);
+        }
+    }
+
+    static class ChildViewHolder {
+        TextView list_name, list_uuid, list_ablity;
+        CheckBox uuidCheckbox, notifyCheckbox, indicateCheckbox;
+        public ChildViewHolder(View view) {
+            list_name = (TextView) view.findViewById(R.id.service_name);
+            list_uuid = (TextView) view.findViewById(R.id.uuid_list);
+            list_ablity = (TextView) view.findViewById(R.id.ablity_name);
+
+//            uuidCheckbox = (CheckBox) view.findViewById(R.id.checkBox1);
+            notifyCheckbox = (CheckBox) view.findViewById(R.id.checkBox2);
+            indicateCheckbox = (CheckBox) view.findViewById(R.id.checkBox3);
+        }
+    }
+
+}

+ 37 - 0
app/src/main/java/com/slam/bboxble/UUIDCheckList.java

@@ -0,0 +1,37 @@
+package com.slam.bboxble;
+
+/**
+ * Created by vers on 2017/8/1.
+ */
+
+public class UUIDCheckList {
+    private boolean isUUIDChecked, isNotifyChecked, isIndicateChecked;
+    private  boolean canWrite, canNotify, canIndicate;
+
+    public UUIDCheckList()
+    {
+        canIndicate = false;
+        canNotify = false;
+        canWrite = false;
+        isUUIDChecked = false;
+        isNotifyChecked = false;
+        isIndicateChecked = false;
+    }
+
+    public void setWriteFlag (boolean flag)
+    {
+        canWrite = flag;
+    }
+
+    public void setNotifyFlag (boolean flag)
+    {
+        canNotify = flag;
+    }
+
+    public void setIndicateFlag (boolean flag)
+    {
+        canIndicate = flag;
+    }
+
+
+}

BIN
app/src/main/res/drawable-hdpi/beken_logo.png


BIN
app/src/main/res/drawable-hdpi/beken_logo_full.jpg


BIN
app/src/main/res/drawable-hdpi/device.png


BIN
app/src/main/res/drawable-hdpi/ic_1489773184_device_power_outline_stroke.png


BIN
app/src/main/res/drawable-hdpi/ic_1489773512_device_power_glyph.png


BIN
app/src/main/res/drawable-hdpi/ic_action_about.png


BIN
app/src/main/res/drawable-hdpi/ic_action_bluetooth.png


BIN
app/src/main/res/drawable-hdpi/ic_action_cancel.png


BIN
app/src/main/res/drawable-hdpi/ic_action_refresh.png


BIN
app/src/main/res/drawable-hdpi/ic_action_settings.png


BIN
app/src/main/res/drawable-hdpi/ic_bluetooth_connected_black_48dp.png


BIN
app/src/main/res/drawable-hdpi/ic_bluetooth_disabled_black_48dp.png


BIN
app/src/main/res/drawable-hdpi/ic_delete_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_delete_forever_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_highlight_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_highlight_off_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_launcher.png


BIN
app/src/main/res/drawable-hdpi/ic_play_arrow_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_portable_wifi_off_black_48dp.png


BIN
app/src/main/res/drawable-hdpi/ic_replay_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_stop_black_24dp.png


BIN
app/src/main/res/drawable-hdpi/ic_wifi_tethering_black_48dp.png


BIN
app/src/main/res/drawable-hdpi/tile.9.png


BIN
app/src/main/res/drawable-mdpi/beken_logo.png


BIN
app/src/main/res/drawable-mdpi/beken_logo_full.jpg


BIN
app/src/main/res/drawable-mdpi/device.png


BIN
app/src/main/res/drawable-mdpi/ic_1489773184_device_power_outline_stroke.png


BIN
app/src/main/res/drawable-mdpi/ic_1489773512_device_power_glyph.png


BIN
app/src/main/res/drawable-mdpi/ic_action_about.png


BIN
app/src/main/res/drawable-mdpi/ic_action_bluetooth.png


BIN
app/src/main/res/drawable-mdpi/ic_action_cancel.png


BIN
app/src/main/res/drawable-mdpi/ic_action_refresh.png


BIN
app/src/main/res/drawable-mdpi/ic_action_settings.png


BIN
app/src/main/res/drawable-mdpi/ic_bluetooth_connected_black_48dp.png


BIN
app/src/main/res/drawable-mdpi/ic_bluetooth_disabled_black_48dp.png


BIN
app/src/main/res/drawable-mdpi/ic_delete_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_delete_forever_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_highlight_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_highlight_off_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_launcher.png


BIN
app/src/main/res/drawable-mdpi/ic_play_arrow_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_portable_wifi_off_black_48dp.png


BIN
app/src/main/res/drawable-mdpi/ic_replay_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_stop_black_24dp.png


BIN
app/src/main/res/drawable-mdpi/ic_wifi_tethering_black_48dp.png


+ 34 - 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml

@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportHeight="108"
+    android:viewportWidth="108">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+        android:strokeColor="#00000000"
+        android:strokeWidth="1" />
+</vector>

BIN
app/src/main/res/drawable-xhdpi/beken_logo.png


BIN
app/src/main/res/drawable-xhdpi/beken_logo_full.jpg


BIN
app/src/main/res/drawable-xhdpi/device.png


BIN
app/src/main/res/drawable-xhdpi/ic_1489773184_device_power_outline_stroke.png


BIN
app/src/main/res/drawable-xhdpi/ic_1489773512_device_power_glyph.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_about.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_bluetooth.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_cancel.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_refresh.png


BIN
app/src/main/res/drawable-xhdpi/ic_action_settings.png


BIN
app/src/main/res/drawable-xhdpi/ic_bluetooth_connected_black_48dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_bluetooth_disabled_black_48dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_delete_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_delete_forever_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_highlight_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_highlight_off_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_launcher.png


BIN
app/src/main/res/drawable-xhdpi/ic_play_arrow_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_portable_wifi_off_black_48dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_replay_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_stop_black_24dp.png


BIN
app/src/main/res/drawable-xhdpi/ic_wifi_tethering_black_48dp.png


BIN
app/src/main/res/drawable-xxhdpi/beken_logo.png


BIN
app/src/main/res/drawable-xxhdpi/beken_logo_full.jpg


BIN
app/src/main/res/drawable-xxhdpi/device.png


BIN
app/src/main/res/drawable-xxhdpi/ic_1489773184_device_power_outline_stroke.png


BIN
app/src/main/res/drawable-xxhdpi/ic_1489773512_device_power_glyph.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_about.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_bluetooth.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_cancel.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_refresh.png


BIN
app/src/main/res/drawable-xxhdpi/ic_action_settings.png


BIN
app/src/main/res/drawable-xxhdpi/ic_bluetooth_connected_black_48dp.png


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác