├── LICENSE ├── README.md └── blefotalib ├── .gitignore ├── blefotalib.iml ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── kr │ └── co │ └── sevencore │ └── blefotalib │ └── ApplicationTest.java └── main ├── AndroidManifest.xml ├── aidl └── kr │ └── co │ └── sevencore │ └── blefotalib │ ├── IBflDeviceScanSvc.aidl │ ├── IBflFwDownloadSvc.aidl │ └── IBflFwUploadSvc.aidl ├── java └── kr │ └── co │ └── sevencore │ └── blefotalib │ ├── BflAttributes.java │ ├── BflCodeList.java │ ├── BflDeviceListAdapter.java │ ├── BflDeviceScanService.java │ ├── BflDeviceScanner.java │ ├── BflFwDownloadService.java │ ├── BflFwDownloader.java │ ├── BflFwUploadService.java │ ├── BflFwUploader.java │ ├── BflFwVerChecker.java │ └── BflUtil.java └── res ├── drawable-hdpi └── ic_launcher.png ├── drawable-mdpi └── ic_launcher.png ├── drawable-xhdpi └── ic_launcher.png ├── drawable-xxhdpi └── ic_launcher.png ├── drawable ├── field_of_business.png └── logo.png ├── layout └── bfl_listitem_device.xml └── values ├── strings.xml └── styles.xml /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BLEFOTA 2 | Bluetooth Low Energy based FOTA solution 3 | 4 | BLE FOTA project is Bluetooth Low Energy(BLE, Bluetooth Smart) based FOTA(Firmware Over The Air) solution for IoT and etc. devices. 5 | 6 | This solution helps to manage a variety of devices in a batch by using smart devices as a gateway and the server as a firmware management. 7 | Because many IoT devices and small-things use BLE and etc. which are low-power, short range wireless communication technology. 8 | There are three principal reasons that the BLE FOTA solution is useful. First, devices are possible to perform continuous firmware update on the side of performance and security. Second, arrangement environment and product types of devices cause the difficulty of firmware management. Third, it is difficult to manage a variety of devices in a batch. BLE FOTA solution is composed of BLE based device, smart device and remote server. And so the devices are able to do FOTA by omnipresent smart devices and be managed by remote server, and besides heterogeneous devices can be an applicable object of BLE FOTA solution by BLE FOTA profile. 9 | 10 | In this project, we present the android library project and profile specification as an open source. 11 | -------------------------------------------------------------------------------- /blefotalib/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /blefotalib/blefotalib.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /blefotalib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 21 5 | buildToolsVersion "21.1.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 18 9 | targetSdkVersion 21 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | } 24 | -------------------------------------------------------------------------------- /blefotalib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:/adt/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /blefotalib/src/androidTest/java/kr/co/sevencore/blefotalib/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /blefotalib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 42 | 43 | 44 | 48 | 49 | 50 | 54 | 55 | 56 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /blefotalib/src/main/aidl/kr/co/sevencore/blefotalib/IBflDeviceScanSvc.aidl: -------------------------------------------------------------------------------- 1 | // IBflDeviceScanSvc.aidl 2 | package kr.co.sevencore.blefotalib; 3 | 4 | // Declare any non-default types here with import statements 5 | 6 | /** 7 | * IBflDeviceScanSvc.aidl 8 | * 9 | * 2015 SEVENCORE Co., Ltd. 10 | * 11 | * @author Jungwoo Park 12 | * @version 1.0.0 13 | * @since 2015-05-04 14 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 15 | */ 16 | interface IBflDeviceScanSvc { 17 | 18 | boolean initScan(); 19 | 20 | void setScanPeriod(long period); 21 | 22 | void setScanState(boolean enable); 23 | 24 | /** 25 | * Demonstrates some basic types that you can use as parameters 26 | * and return values in AIDL. 27 | */ 28 | void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 29 | double aDouble, String aString); 30 | } 31 | -------------------------------------------------------------------------------- /blefotalib/src/main/aidl/kr/co/sevencore/blefotalib/IBflFwDownloadSvc.aidl: -------------------------------------------------------------------------------- 1 | // IBflFwDownloadSvc.aidl 2 | package kr.co.sevencore.blefotalib; 3 | 4 | // Declare any non-default types here with import statements 5 | 6 | /** 7 | * IBflFwDownloadSvc.aidl 8 | * 9 | * 2015 SEVENCORE Co., Ltd. 10 | * 11 | * @author Jungwoo Park 12 | * @version 1.0.0 13 | * @since 2015-05-04 14 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 15 | */ 16 | interface IBflFwDownloadSvc { 17 | 18 | boolean initDownloader(); 19 | 20 | void getFirmwareUrl(); 21 | 22 | /** 23 | * Demonstrates some basic types that you can use as parameters 24 | * and return values in AIDL. 25 | */ 26 | void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 27 | double aDouble, String aString); 28 | } 29 | -------------------------------------------------------------------------------- /blefotalib/src/main/aidl/kr/co/sevencore/blefotalib/IBflFwUploadSvc.aidl: -------------------------------------------------------------------------------- 1 | // IBflFwUploadSvc.aidl 2 | package kr.co.sevencore.blefotalib; 3 | 4 | // Declare any non-default types here with import statements 5 | 6 | /** 7 | * IBflFwUploadSvc.aidl 8 | * 9 | * 2015 SEVENCORE Co., Ltd. 10 | * 11 | * @author Jungwoo Park 12 | * @version 1.0.0 13 | * @since 2015-05-04 14 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 15 | */ 16 | interface IBflFwUploadSvc { 17 | 18 | boolean initUploader(); 19 | 20 | boolean connect(String address); 21 | 22 | void disconnect(); 23 | 24 | void close(); 25 | 26 | void updateGatt(); 27 | 28 | boolean checkProperty(int serviceIdx, int characteristicIdx); 29 | 30 | void executeReadCharacteristic(int serviceIdx, int characteristicIdx); 31 | 32 | void executeWriteFirmwareNewVersion(int serviceIdx, int characteristicIdx, String firmwareVersion); 33 | 34 | void executeWriteFirmwareData(int serviceIdx, int characteristicIdx, String filePath, int sequenceNumber); 35 | 36 | void executeWriteSequenceNumber(int serviceIdx, int characteristicIdx, int index); 37 | 38 | void executeWriteChecksumData(int serviceIdx, int characteristicIdx, String filePath); 39 | 40 | void executeWriteFirmwareUpgradeType(int serviceIdx, int characteristicIdx, byte typeFlag); 41 | 42 | void executeWriteReset(int serviceIdx, int characteristicIdx, byte resetFlag); 43 | 44 | /** 45 | * Demonstrates some basic types that you can use as parameters 46 | * and return values in AIDL. 47 | */ 48 | void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 49 | double aDouble, String aString); 50 | } 51 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflAttributes.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * BflAttributes.java 7 | * BLE FOTA profile Attributes. 8 | * This class includes a GATT based attributes of "Firmware upgrade profile". 9 | * 10 | * Copyright 2015 SEVENCORE Co., Ltd. 11 | * 12 | * @author Jungwoo Park 13 | * @version 1.0.0 14 | * @since 2015-04-08 15 | */ 16 | public class BflAttributes { 17 | private static HashMap attributes = new HashMap(); 18 | 19 | // PRIMARY SERVICE: GAP SERVICE 20 | // CHARACTERISTIC: GAP DEVICE NAME | GAP APPEARANCE | PERIPHERAL PREFERRED CONNECTION PARAMETERS 21 | public static String DEVICE_NAME = "00002a00-0000-1000-8000-00805f9b34fb"; 22 | public static String APPEARANCE = "00002a01-0000-1000-8000-00805f9b34fb"; 23 | public static String PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS = "00002a04-0000-1000-8000-00805f9b34fb"; 24 | 25 | // PRIMARY SERVICE: GATT SERVICE 26 | // CHARACTERISTIC: SERVICE CHANGED 27 | public static String SERVICE_CHANGED = "00001801-0000-1000-8000-00805f9b34fb"; 28 | 29 | // PRIMARY SERVICE: FIRMWARE UPGRADE - INCLUDE: DEVICE INFORMATION 30 | // CHARACTERISTIC: FIRMWARE VERSION | FIRMWARE NEW VERSION | FIRMWARE DATA | SEQUENCE NUMBER | CHECKSUM DATA | FIRMWARE DATA CHECK | FIRMWARE UPGRADE TYPE | FIRMWARE STATUS | RESET 31 | public static String FIRMWARE_VERSION = "00002af0-0000-1000-8000-00805f9b34fb"; // READ 32 | public static String FIRMWARE_NEW_VERSION = "00002af1-0000-1000-8000-00805f9b34fb"; // READ | WRITE 33 | public static String FIRMWARE_DATA = "00002af2-0000-1000-8000-00805f9b34fb"; // WRITE 34 | public static String SEQUENCE_NUMBER = "00002af3-0000-1000-8000-00805f9b34fb"; // READ | WRITE 35 | public static String CHECKSUM_DATA = "00002af4-0000-1000-8000-00805f9b34fb"; // WRITE 36 | public static String FIRMWARE_DATA_CHECK = "00002af5-0000-1000-8000-00805f9b34fb"; // NOTIFY | READ 37 | public static String FIRMWARE_UPGRADE_TYPE = "00002af6-0000-1000-8000-00805f9b34fb"; // WRITE 38 | public static String FIRMWARE_STATUS = "00002af7-0000-1000-8000-00805f9b34fb"; // NOTIFY | READ 39 | public static String RESET ="00002af8-0000-1000-8000-00805f9b34fb"; // WRITE 40 | 41 | // SECONDARY SERVICE: DEVICE INFORMATION 42 | // CHARACTERISTIC: MANUFACTURER NAME | MODEL NUMBER | SERIAL NUMBER 43 | public static String MANUFACTURER_NAME = "00002a29-0000-1000-8000-00805f9b34fb"; // READ 44 | public static String MODEL_NUMBER = "00002a24-0000-1000-8000-00805f9b34fb"; // READ 45 | public static String SERIAL_NUMBER = "00002a25-0000-1000-8000-00805f9b34fb"; // READ 46 | 47 | // FIRMWARE_DATA_CHECK & FIRMWARE_STATUS NOTIFICATION USING THIS CHARACTERISTIC 48 | public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; 49 | 50 | 51 | static { 52 | // FIRMWARE UPGRADE RELATED SERVICES 53 | attributes.put("00001800-0000-1000-8000-00805f9b34fb", "Generic Access"); 54 | attributes.put("00001801-0000-1000-8000-00805f9b34fb", "Generic Attributes"); 55 | attributes.put("000018ff-0000-1000-8000-00805f9b34fb", "Firmware Upgrade Service"); 56 | attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service"); 57 | 58 | // GENERIC ACCESS SERVICE 59 | attributes.put(DEVICE_NAME,"Device Name"); 60 | attributes.put(APPEARANCE,"Appearance"); 61 | attributes.put(PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS,"Peripheral Pref. Conn. Params"); 62 | 63 | // GENERIC ATTRIBUTE SERVICE 64 | attributes.put(SERVICE_CHANGED, "Service Changed"); 65 | 66 | // FIRMWARE UPGRADE SERVICE 67 | attributes.put(FIRMWARE_VERSION, "Firmware Version"); 68 | attributes.put(FIRMWARE_NEW_VERSION, "Firmware New Version"); 69 | attributes.put(FIRMWARE_DATA, "Firmware Data"); 70 | attributes.put(SEQUENCE_NUMBER, "Sequence Number"); 71 | attributes.put(CHECKSUM_DATA, "Checksum Data"); 72 | attributes.put(FIRMWARE_DATA_CHECK, "Firmware Data Check"); 73 | attributes.put(FIRMWARE_UPGRADE_TYPE, "Firmware Upgrade Type"); 74 | attributes.put(FIRMWARE_STATUS, "Firmware Status"); 75 | attributes.put(RESET, "Reset"); 76 | 77 | // DEVICE INFORMATION SERVICE 78 | attributes.put(MANUFACTURER_NAME, "Manufacturer Name"); 79 | attributes.put(MODEL_NUMBER, "Model Number"); 80 | attributes.put(SERIAL_NUMBER, "Serial Number"); 81 | } 82 | 83 | /** 84 | * Search a content of attributes. 85 | * 86 | * @param uuid is unique value of each attributes. 87 | * @param defaultName is a default value for not reserved attribute. 88 | * @return a content of the specific attribute. 89 | */ 90 | public static String lookup(String uuid, String defaultName) { 91 | String name = attributes.get(uuid); 92 | return name == null ? defaultName : name; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflCodeList.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | /** 4 | * BflCodeList.java 5 | * BLE FOTA Library code list. 6 | * 7 | * 2015 SEVENCORE Co., Ltd. 8 | * 9 | * @author Jungwoo Park 10 | * @version 1.0.0 11 | * @since 2015-07-15 12 | * @see kr.co.sevencore.blefotalib.BflFwDownloader 13 | * @see kr.co.sevencore.blefotalib.BflFwUploader 14 | */ 15 | public class BflCodeList { 16 | public final static String LIST_NAME = "NAME"; // Services or characteristics name. 17 | public final static String LIST_UUID = "UUID"; // Services or characteristics UUID. 18 | 19 | 20 | /** 21 | * Firmware upload each state message. 22 | */ 23 | public enum UploadCode { 24 | DEVICE_FIRMWARE_CURRENT_VERSION("3000"), 25 | DEVICE_FIRMWARE_NEW_VERSION("3010"), 26 | DEVICE_FIRMWARE_NEW_VERSION_EMPTINESS("3011"), 27 | DEVICE_FIRMWARE_NEW_VERSION_EXISTENCE("3012"), 28 | DEVICE_FIRMWARE_SEQUENCE_NUMBER("3020"), 29 | DEVICE_FIRMWARE_AVAILABLE_SEQUENCE_NUMBER("3021"), 30 | DEVICE_FIRMWARE_DATA_LEFT_COUNT("3022"), 31 | DEVICE_FIRMWARE_WRITABLE_SEQUENCE_NUMBER("3023"), 32 | DEVICE_FIRMWARE_DATA_STATUS("3030"), 33 | DEVICE_FIRMWARE_DATA_STATUS_NORMAL("3031"), 34 | DEVICE_FIRMWARE_DATA_STATUS_VALID("3032"), 35 | DEVICE_FIRMWARE_DATA_STATUS_INVALID("3033"), 36 | DEVICE_FIRMWARE_UPGRADE_TYPE("3040"), 37 | DEVICE_FIRMWARE_UPGRADE_TYPE_NORMAL("3041"), 38 | DEVICE_FIRMWARE_UPGRADE_TYPE_FORCED("3042"), 39 | DEVICE_FIRMWARE_STATUS("3050"), 40 | DEVICE_FIRMWARE_STATUS_NORMAL("3051"), 41 | DEVICE_FIRMWARE_STATUS_SUCCESSFUL_FINISH("3052"), 42 | DEVICE_FIRMWARE_STATUS_ABNORMAL_FINISH("3053"), 43 | DEVICE_FIRMWARE_RESET("3060"), 44 | DEVICE_INFORMATION_MANUFACTURER_NAME("3100"), 45 | DEVICE_INFORMATION_MODEL_NUMBER("3101"), 46 | DEVICE_INFORMATION_SERIAL_NUMBER("3102"), 47 | DEVICE_EXTRA_DATA("3200"); 48 | 49 | private final String code; 50 | 51 | UploadCode(String code) { 52 | this.code = code; 53 | } 54 | 55 | /** 56 | * Get code value. 57 | * 58 | * @return String type code number. 59 | */ 60 | public String getCode() { 61 | return code; 62 | } 63 | } 64 | 65 | /** 66 | * FOTA profile services index. 67 | */ 68 | public enum ServiceIdxCode { 69 | SERVICE_FIRMWARE_UPGRADE(2), // FOTA service index in mBflGattCharacteristics. 70 | SERVICE_DEVICE_INFO(3); // Device info service index in mBflGattCharacteristics. 71 | 72 | private final int code; 73 | 74 | ServiceIdxCode(int code) { 75 | this.code = code; 76 | } 77 | 78 | /** 79 | * Get code value. 80 | * 81 | * @return Integer type index value. 82 | */ 83 | public int getCode() { 84 | return code; 85 | } 86 | } 87 | 88 | /** 89 | * FOTA characteristic index. 90 | */ 91 | public enum CharacteristicFotaIdxCode { 92 | CHARACTERISTIC_FIRMWARE_VERSION(0), // Firmware version characteristic in firmware upgrade service. 93 | CHARACTERISTIC_FIRMWARE_NEW_VERSION(1),// Firmware new version characteristic in firmware upgrade service. 94 | CHARACTERISTIC_FIRMWARE_DATA(2), // Firmware data characteristic in firmware upgrade service. 95 | CHARACTERISTIC_SEQUENCE_NUMBER(3), // Sequence number characteristic in firmware upgrade service. 96 | CHARACTERISTIC_CHECKSUM_DATA(4), // Checksum characteristic in firmware upgrade service. 97 | CHARACTERISTIC_FIRMWARE_DATA_CHECK(5), // Firmware data check characteristic in firmware upgrade service. 98 | CHARACTERISTIC_FIRMWARE_UPGRADE_TYPE(6),// Firmware upgrade type characteristic in firmware upgrade service. 99 | CHARACTERISTIC_FIRMWARE_STATUS(7), // Firmware status characteristic in firmware upgrade service. 100 | CHARACTERISTIC_RESET(8); // Reset characteristic in firmware upgrade service. 101 | 102 | private final int code; 103 | 104 | CharacteristicFotaIdxCode(int code) { 105 | this.code = code; 106 | } 107 | 108 | /** 109 | * Get code value. 110 | * 111 | * @return Integer type index value. 112 | */ 113 | public int getCode() { 114 | return code; 115 | } 116 | } 117 | 118 | /** 119 | * Device information characteristic index. 120 | */ 121 | public enum CharacteristicDeviceInfoIdxCode { 122 | CHARACTERISTIC_MANUFACTURER_NAME(0), // Manufacturer name characteristic in device information service. 123 | CHARACTERISTIC_MODEL_NUMBER(1), // Model number characteristic in device information service. 124 | CHARACTERISTIC_SERIAL_NUMBER(2); // Serial number characteristic in device information service. 125 | 126 | private final int code; 127 | 128 | CharacteristicDeviceInfoIdxCode(int code) { 129 | this.code = code; 130 | } 131 | 132 | /** 133 | * Get code value. 134 | * 135 | * @return Integer type index value. 136 | */ 137 | public int getCode() { 138 | return code; 139 | } 140 | } 141 | 142 | /** 143 | * Firmware version status classification. 144 | */ 145 | public enum FirmwareVersionStatusCode { 146 | FIRMWARE_VERSION_UP_TO_DATE(0), 147 | FIRMWARE_VERSION_DOWNGRADE(1), 148 | FIRMWARE_VERSION_UPGRADE(2); 149 | 150 | private final int code; 151 | 152 | FirmwareVersionStatusCode(int code) { 153 | this.code = code; 154 | } 155 | 156 | /** 157 | * Get code value. 158 | * 159 | * @return Integer code value. 160 | */ 161 | public int getCode() { 162 | return code; 163 | } 164 | } 165 | 166 | /** 167 | * Firmware upgrade type classification. 168 | */ 169 | public enum UpgradeVersionTypeCode { 170 | FIRMWARE_MAJOR_UPGRADE(0), 171 | FIRMWARE_MINOR_UPGRADE(1), 172 | FIRMWARE_MAJOR_DOWNGRADE(2), 173 | FIRMWARE_MINOR_DOWNGRADE(3), 174 | FIRMWARE_UP_TO_DATE(4); 175 | 176 | private final int code; 177 | 178 | UpgradeVersionTypeCode(int code) { 179 | this.code = code; 180 | } 181 | 182 | /** 183 | * Get code value. 184 | * 185 | * @return Integer code value. 186 | */ 187 | public int getCode() { 188 | return code; 189 | } 190 | } 191 | 192 | /** 193 | * Firmware data integrity status code. 194 | */ 195 | public enum FirmwareDataCheckCode { 196 | FIRMWARE_DATA_CHECK_NORMAL("0"), 197 | FIRMWARE_DATA_CHECK_VALIDATE("1"), 198 | FIRMWARE_DATA_CHECK_INVALIDATE("2"); 199 | 200 | private final String code; 201 | 202 | FirmwareDataCheckCode(String code) { 203 | this.code = code; 204 | } 205 | 206 | /** 207 | * Get code value. 208 | * 209 | * @return String type code value. 210 | */ 211 | public String getCode() { 212 | return code; 213 | } 214 | } 215 | 216 | /** 217 | * Firmware status code. 218 | */ 219 | public enum FirmwareStatusCode { 220 | FIRMWARE_STATUS_NORMAL("0"), 221 | FIRMWARE_STATUS_SUCCESSFUL("1"), 222 | FIRMWARE_STATUS_ABNORMAL_FINISH("2"); 223 | 224 | private final String code; 225 | 226 | FirmwareStatusCode(String code) { 227 | this.code = code; 228 | } 229 | 230 | /** 231 | * Get code value. 232 | * 233 | * @return String type code value. 234 | */ 235 | public String getCode() { 236 | return code; 237 | } 238 | } 239 | 240 | /** 241 | * Firmware download each state message. 242 | */ 243 | public enum DownloadCode { 244 | SERVER_CONN_ERROR_UNKNOWN_DEVICE("7000"), 245 | SERVER_CONN_PROCESS_PRODUCT_INFO("7100"), 246 | SERVER_CONN_PROCESS_CHECKING_VERSION("7101"), 247 | SERVER_CONN_PROCESS_GETTING_VERSION_NAME("7102"), 248 | SERVER_CONN_PROCESS_URL_INFO("7103"), 249 | SERVER_CONN_PROCESS_GETTING_FIRMWARE("7104"), 250 | FIRMWARE_DOWNLOAD_PROCESS_STARTING_DOWNLOAD("7200"), 251 | FIRMWARE_DOWNLOAD_PROGRESSING("7201"), 252 | FIRMWARE_DOWNLOAD_ERROR_INVALIDATE_DATA("7202"), 253 | FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD("7203"); 254 | 255 | private final String code; 256 | 257 | DownloadCode(String code) { 258 | this.code = code; 259 | } 260 | 261 | /** 262 | * Get code value. 263 | * 264 | * @return String type code number. 265 | */ 266 | public String getCode() { 267 | return code; 268 | } 269 | } 270 | 271 | /** 272 | * BLE FOTA Library error code. 273 | * Not in use now. Reserved. 274 | */ 275 | public enum BflErrorCode { 276 | NOT_ERROR(1000), 277 | BLE_NOT_SUPPORT(1010), 278 | BT_NOT_SUPPORT(1011), 279 | BT_DISABLED(1020), 280 | BT_MANAGER_INIT_FAIL(1021), 281 | BT_ADAPTER_OBTAINMENT_FAIL(1022), 282 | WIFI_DISABLED(1030), 283 | MOBILE_NOT_AVAILABLE(1040), 284 | ERROR_UNKNOWN_DEVICE(1050), 285 | ERROR_INVALIDATE_DATA(1060); 286 | 287 | private final int errCode; 288 | 289 | BflErrorCode(int errCode) { 290 | this.errCode = errCode; 291 | } 292 | 293 | /** 294 | * Get error code value. 295 | * 296 | * @return Error code number. 297 | */ 298 | public int getErrCode() { 299 | return errCode; 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflDeviceListAdapter.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.BaseAdapter; 8 | import android.widget.TextView; 9 | 10 | import java.util.ArrayList; 11 | 12 | /** 13 | * BflDeviceListAdapter.java 14 | * BLE FOTA Library Device List Adapter. 15 | * 16 | * 2015 SEVENCORE Co., Ltd. 17 | * 18 | * @author Jungwoo Park 19 | * @version 1.0.0 20 | * @since 2015-06-05 21 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner 22 | */ 23 | public class BflDeviceListAdapter extends BaseAdapter { 24 | private final static String BLE_FOTA_TAG = BflDeviceListAdapter.class.getSimpleName(); 25 | 26 | private ArrayList mLeDevices; 27 | private LayoutInflater mInflater; 28 | 29 | 30 | public BflDeviceListAdapter(Context context) { 31 | this.mLeDevices = new ArrayList(); 32 | this.mInflater = LayoutInflater.from(context); 33 | } 34 | 35 | public class BleDevice { 36 | public String macAddress; 37 | public String bleDeviceName; 38 | public int bleRssi; 39 | // add unit 40 | 41 | public BleDevice(String macAddress, String bleDeviceName, int bleRssi) { 42 | this.macAddress = macAddress; 43 | this.bleDeviceName = bleDeviceName; 44 | this.bleRssi = bleRssi; 45 | } 46 | } 47 | 48 | /** 49 | * Add the device information in the list. 50 | * 51 | * @param macAddress is MAC address of the device. 52 | * @param deviceName is device name composed of string. 53 | */ 54 | public void addDevice(String macAddress, String deviceName, int rssi) { 55 | boolean uniqueFlag = true; 56 | 57 | if (!mLeDevices.isEmpty()) { 58 | for(int i = 0; i < mLeDevices.size(); i++) { 59 | if (mLeDevices.get(i).macAddress.equals(macAddress)) { 60 | uniqueFlag = false; 61 | break; 62 | } 63 | } 64 | } 65 | 66 | if (uniqueFlag) { 67 | mLeDevices.add(new BleDevice(macAddress, deviceName, rssi)); 68 | } 69 | } 70 | 71 | /** 72 | * Get the device information of the selected position. 73 | * 74 | * @param position is the selected item in the list. 75 | * @return the device information. 76 | */ 77 | public BleDevice getDevice(int position) { 78 | return mLeDevices.get(position); 79 | } 80 | 81 | /** 82 | * Clear device list. 83 | */ 84 | public void clear() { 85 | mLeDevices.clear(); 86 | } 87 | 88 | /** 89 | * Get the total count of the data. 90 | * 91 | * @return The total count. 92 | */ 93 | @Override 94 | public int getCount() { 95 | return mLeDevices.size(); 96 | } 97 | 98 | /** 99 | * Get data of the specific position. 100 | * 101 | * @param i is the selected position. 102 | * @return Data of the selected position. 103 | */ 104 | @Override 105 | public Object getItem(int i) { 106 | return mLeDevices.get(i); 107 | } 108 | 109 | /** 110 | * Get the item position of the selected item. 111 | * 112 | * @param i is the selected item. 113 | * @return is the position of the selected item. 114 | */ 115 | @Override 116 | public long getItemId(int i) { 117 | return i; 118 | } 119 | 120 | /** 121 | * The adapter & view are used to show scanned device list on the list view. 122 | */ 123 | @Override 124 | public View getView(int i, View view, ViewGroup viewGroup) { 125 | ViewHolder viewHolder; 126 | // General ListView optimization code. 127 | if (view == null) { 128 | view = mInflater.inflate(R.layout.bfl_listitem_device, null); 129 | viewHolder = new ViewHolder(); 130 | viewHolder.deviceAddress = (TextView) view.findViewById(R.id.device_address); 131 | viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name); 132 | viewHolder.deviceRssi = (TextView) view.findViewById(R.id.device_rssi); 133 | view.setTag(viewHolder); 134 | } else { 135 | viewHolder = (ViewHolder) view.getTag(); 136 | } 137 | 138 | final String deviceName = mLeDevices.get(i).bleDeviceName; 139 | if (deviceName != null && deviceName.length() > 0) 140 | viewHolder.deviceName.setText(deviceName); 141 | else 142 | viewHolder.deviceName.setText(R.string.unknown_device); 143 | viewHolder.deviceAddress.setText(mLeDevices.get(i).macAddress); 144 | viewHolder.deviceRssi.setText(Integer.toString(mLeDevices.get(i).bleRssi)); 145 | 146 | return view; 147 | } 148 | 149 | static class ViewHolder { 150 | TextView deviceName; 151 | TextView deviceAddress; 152 | TextView deviceRssi; 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflDeviceScanService.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.app.Service; 4 | import android.bluetooth.BluetoothAdapter; 5 | import android.bluetooth.BluetoothDevice; 6 | import android.bluetooth.BluetoothManager; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.os.Handler; 10 | import android.os.IBinder; 11 | import android.os.RemoteException; 12 | import android.util.Log; 13 | 14 | /** 15 | * BflDeviceScanService.java 16 | * BLE FOTA Library Scanning BLE devices Service. 17 | * 18 | * 2015 SEVENCORE Co., Ltd. 19 | * 20 | * @author Jungwoo Park 21 | * @version 1.0.0 22 | * @since 2015-04-08 23 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner 24 | * @see kr.co.sevencore.blefotalib.IBflDeviceScanSvc 25 | */ 26 | public class BflDeviceScanService extends Service { 27 | private final static String BLE_FOTA_TAG = BflDeviceScanService.class.getSimpleName(); 28 | 29 | private BluetoothManager mBflBluetoothManager; 30 | private BluetoothAdapter mBflBluetoothAdapter; 31 | 32 | private Handler mBflScanHandler; 33 | private long mBflScanPeriod = 10000; // Stops scanning after 10 seconds. 34 | 35 | // Reserved for immortal background (device scanning) service. 36 | /*private static PowerManager sPowerManager; 37 | private static PowerManager.WakeLock sCpuWakeLock = null;*/ 38 | 39 | public final static String ACTION_BFL_SCAN_STATE_DATA = 40 | "kr.co.sevencore.ble.fota.lib.ACTION_SCAN_STATE_DATA"; 41 | public final static String ACTION_BFL_SCAN_DATA = 42 | "kr.co.sevencore.ble.fota.lib.ACTION_SCAN_DATA"; 43 | public final static String EXTRA_BFL_SCAN_STATE_DATA = 44 | "kr.co.sevencore.ble.fota.lib.SCAN_STATE_DATA"; 45 | public final static String EXTRA_BFL_MAC_ADDRESS_DATA = 46 | "kr.co.sevencore.ble.fota.lib.MAC_ADDRESS_DATA"; 47 | public final static String EXTRA_BFL_DEVICE_NAME_DATA = 48 | "kr.co.sevencore.ble.fota.lib.DEVICE_NAME_DATA"; 49 | public final static String EXTRA_BFL_RSSI_DATA = 50 | "kr.co.sevencore.ble.fota.lib.RSSI_DATA"; 51 | 52 | 53 | public BflDeviceScanService() {} 54 | 55 | @Override 56 | public IBinder onBind(Intent intent) { 57 | return mBflScanBinder; 58 | } 59 | 60 | IBflDeviceScanSvc.Stub mBflScanBinder = new IBflDeviceScanSvc.Stub() { 61 | 62 | /** 63 | * Initializes a reference to the local Bluetooth adapter. 64 | * 65 | * @return Return true if the initialization is successful. 66 | * @throws RemoteException 67 | */ 68 | @Override 69 | public boolean initScan() throws RemoteException { 70 | // For API level 18 and above, get a reference to BluetoothAdapter through BluetoothManager. 71 | if (mBflBluetoothManager == null) { 72 | mBflBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 73 | if (mBflBluetoothManager == null) { 74 | Log.e(BLE_FOTA_TAG, "Unable to initialize BluetoothManager."); 75 | return false; 76 | } 77 | } 78 | 79 | mBflBluetoothAdapter = mBflBluetoothManager.getAdapter(); 80 | if (mBflBluetoothAdapter == null) { 81 | Log.e(BLE_FOTA_TAG, "Unable to obtain a BluetoothAdapter."); 82 | return false; 83 | } 84 | 85 | scanBflLeDevice(true); 86 | return true; 87 | } 88 | 89 | /** 90 | * Customize scanning period by a user. 91 | * 92 | * @param period of scanning. 93 | * @throws RemoteException 94 | */ 95 | @Override 96 | public void setScanPeriod(long period) throws RemoteException { 97 | mBflScanPeriod = period; 98 | } 99 | 100 | /** 101 | * Start scanning or stop scanning. 102 | * 103 | * @param enable or disable scanning state. 104 | * @throws RemoteException 105 | */ 106 | @Override 107 | public void setScanState(boolean enable) throws RemoteException { 108 | scanBflLeDevice(enable); 109 | } 110 | 111 | @Override 112 | public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 113 | double aDouble, String aString) {} 114 | }; 115 | 116 | @Override 117 | public boolean onUnbind(Intent intent) { 118 | return super.onUnbind(intent); 119 | } 120 | 121 | /** 122 | * Update scanning state. 123 | * 124 | * @param action used for filtering. 125 | * @param scanState is current scanning state. 126 | */ 127 | private void broadcastUpdate(final String action, final boolean scanState) { 128 | final Intent intent = new Intent(action); 129 | intent.putExtra(EXTRA_BFL_SCAN_STATE_DATA, scanState); 130 | sendBroadcast(intent); 131 | } 132 | 133 | /** 134 | * Update BLE device information. 135 | * 136 | * @param action used to filtering. 137 | * @param macAddr is BLE MAC address. 138 | * @param deviceName is BLE device name. 139 | * @param bleRssi is RSSI value, when the device is scanned. 140 | */ 141 | private void broadcastUpdate(final String action, final String macAddr, 142 | final String deviceName, final int bleRssi) { 143 | final Intent intent = new Intent(action); 144 | intent.putExtra(EXTRA_BFL_MAC_ADDRESS_DATA, macAddr); 145 | intent.putExtra(EXTRA_BFL_DEVICE_NAME_DATA, deviceName); 146 | intent.putExtra(EXTRA_BFL_RSSI_DATA, bleRssi); 147 | sendBroadcast(intent); 148 | } 149 | 150 | @Override 151 | public int onStartCommand(Intent intent, int flags, int startId) { 152 | //TODO: START_REDELIVER_INTENT is used for immortal background (BLE device scanning) service. 153 | return START_REDELIVER_INTENT; 154 | } 155 | 156 | @Override 157 | public void onCreate() { 158 | super.onCreate(); 159 | 160 | // CPU wake lock is used to keep service running. 161 | // CPU wake lock is managed by each service(especially scan service) or the main application. 162 | /*sPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 163 | sCpuWakeLock = sPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FIRMWARE_DOWNLOAD"); 164 | sCpuWakeLock.acquire();*/ 165 | 166 | mBflScanHandler = new Handler(); 167 | } 168 | 169 | @Override 170 | public void onDestroy() { 171 | super.onDestroy(); 172 | 173 | /*if (sCpuWakeLock != null) { 174 | sCpuWakeLock.release(); 175 | sCpuWakeLock = null; 176 | }*/ 177 | 178 | mBflBluetoothAdapter = null; 179 | mBflBluetoothManager = null; 180 | 181 | mBflScanHandler.removeMessages(0); 182 | //mBflScanHandler = null; 183 | } 184 | 185 | /** 186 | * Scan BLE device during scanning period. 187 | * Each broadcastUpdates are used to update scanning state. 188 | * 189 | * @param enable is the flag to start or stop scanning. 190 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner 191 | */ 192 | public void scanBflLeDevice(final boolean enable) { 193 | if (enable) { 194 | mBflScanHandler.postDelayed( 195 | new Runnable() { 196 | @Override 197 | public void run() { 198 | broadcastUpdate(ACTION_BFL_SCAN_STATE_DATA, false); 199 | mBflBluetoothAdapter.stopLeScan(mLeScanCallback); 200 | } 201 | }, mBflScanPeriod); 202 | 203 | broadcastUpdate(ACTION_BFL_SCAN_STATE_DATA, true); 204 | 205 | mBflBluetoothAdapter.startLeScan(mLeScanCallback); 206 | } else { 207 | broadcastUpdate(ACTION_BFL_SCAN_STATE_DATA, false); 208 | 209 | mBflBluetoothAdapter.stopLeScan(mLeScanCallback); 210 | } 211 | } 212 | 213 | /** 214 | * BLE scan callback. 215 | */ 216 | private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { 217 | @Override 218 | public void onLeScan(final BluetoothDevice bluetoothDevice, int i, byte[] bytes) { 219 | Log.d(BLE_FOTA_TAG, " Scanning information: " + bluetoothDevice.getAddress() + " " + bluetoothDevice.getName() + "'s RSSI is " + i); 220 | broadcastUpdate(ACTION_BFL_SCAN_DATA, bluetoothDevice.getAddress(), bluetoothDevice.getName(), i); 221 | } 222 | }; 223 | } 224 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflDeviceScanner.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.content.ServiceConnection; 9 | import android.os.IBinder; 10 | import android.os.RemoteException; 11 | import android.util.Log; 12 | 13 | /** 14 | * BflDeviceScanner.java 15 | * BLE FOTA Library Scanning BLE devices. 16 | * 17 | * 2015 SEVENCORE Co., Ltd. 18 | * 19 | * @author Jungwoo Park 20 | * @version 1.0.0 21 | * @since 2015-04-08 22 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 23 | * @see kr.co.sevencore.blefotalib.IBflDeviceScanSvc 24 | * @see kr.co.sevencore.blefotalib.BflDeviceListAdapter 25 | */ 26 | public class BflDeviceScanner { 27 | private final static String BLE_FOTA_TAG = BflDeviceScanner.class.getSimpleName(); 28 | 29 | public IBflDeviceScanSvc mBflScanBinder; // BLE device scan service AIDL. 30 | private Intent mScanServiceIntent; 31 | private boolean mScanning; // The flag used to check scanning or not. 32 | private boolean mScanPeriodFlag = false; // The flag used to customize scanning period. 33 | private long mScanPeriod; // Scanning period defined by user. 34 | 35 | private Context mContext; 36 | 37 | public static BflDeviceListAdapter sLeDeviceListAdapter; // The adapter saving information of scanned BLE devices. 38 | 39 | private OnScanningSvcInit mScanningSvcInitCallback; // Service initialization result of scanning callback. 40 | private OnScannedInfo mScannedCallback; // BLE scan information callback. 41 | private OnScanningState mScanningCallback; // BLE scan state callback. 42 | 43 | 44 | public BflDeviceScanner(Context context) { 45 | mContext = context; 46 | } 47 | 48 | /** 49 | * OnScanningSvcInit interface is used to get result of BLE device scanning service initialization. 50 | */ 51 | public interface OnScanningSvcInit { 52 | /** 53 | * Initialization using BLE of the smart device. 54 | * 55 | * @param initResult true: All of BLE related feature is normal state. 56 | * false: Unable to initialize BLE related feature. 57 | */ 58 | void onScanningSvcInit(boolean initResult); 59 | } 60 | 61 | /** 62 | * OnScannedInfo interface is used to get BLE device information from scanned devices. 63 | */ 64 | public interface OnScannedInfo { 65 | /** 66 | * Scanned BLE device information. 67 | * 68 | * @param address is MAC address. 69 | * @param name is device name. 70 | * @param rssi is RSSI(Received Signal Strength Indicator) value. 71 | */ 72 | void onDeviceInfo(String address, String name, int rssi); 73 | } 74 | 75 | /** 76 | * OnScanningState interface is used to check scanning state. 77 | */ 78 | public interface OnScanningState { 79 | /** 80 | * Notify current scanning state. 81 | * 82 | * @param state true: scanning, false: not scanning. 83 | */ 84 | void onScanningState(boolean state); 85 | } 86 | 87 | /** 88 | * Save a callback object to mScanningSvcInitCallback. 89 | * 90 | * @param callback is OnScanningSvcInit. 91 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner.OnScanningSvcInit 92 | */ 93 | public void setOnScanningSvcInit(OnScanningSvcInit callback) { 94 | mScanningSvcInitCallback = callback; 95 | } 96 | 97 | /** 98 | * Save a callback object to mScannedCallback. 99 | * 100 | * @param callback is OnScannedInfo. 101 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner.OnScannedInfo 102 | */ 103 | public void setOnDeviceInfo(OnScannedInfo callback) { 104 | mScannedCallback = callback; 105 | } 106 | 107 | /** 108 | * Save a callback object to mScanningCallback. 109 | * 110 | * @param callback is OnScanningState. 111 | * @see kr.co.sevencore.blefotalib.BflDeviceScanner.OnScanningState 112 | */ 113 | public void setOnScanningState(OnScanningState callback) { 114 | mScanningCallback = callback; 115 | } 116 | 117 | /** 118 | * Create an object of device list adapter. 119 | * 120 | * @param context is gettable from caller application. 121 | * @see kr.co.sevencore.blefotalib.BflDeviceListAdapter 122 | */ 123 | public void createAdapter(Context context) { 124 | sLeDeviceListAdapter = new BflDeviceListAdapter(context.getApplicationContext()); 125 | } 126 | 127 | /** 128 | * Create an object to implement a service connection interface. 129 | * 130 | * @see kr.co.sevencore.blefotalib.IBflDeviceScanSvc 131 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 132 | */ 133 | private final ServiceConnection mBflScanSvcConnection = new ServiceConnection() { 134 | @Override 135 | public void onServiceConnected(ComponentName name, IBinder service) { 136 | mBflScanBinder = IBflDeviceScanSvc.Stub.asInterface(service); 137 | boolean initResult = true; 138 | 139 | Log.d(BLE_FOTA_TAG, "Unit test mode BLE scanning started."); 140 | // When a user app customizes the scan period, setScanPeriod method is used. 141 | if(mScanPeriodFlag) { 142 | setScanPeriod(mScanPeriod); 143 | mScanPeriodFlag = false; 144 | } 145 | 146 | try { 147 | if (!mBflScanBinder.initScan()) { 148 | initResult = false; 149 | Log.e(BLE_FOTA_TAG, "Unable to initialize Bluetooth"); 150 | } 151 | 152 | if (mScanningSvcInitCallback != null) { 153 | mScanningSvcInitCallback.onScanningSvcInit(initResult); 154 | } 155 | } catch (RemoteException e) { 156 | e.printStackTrace(); 157 | } 158 | } 159 | 160 | @Override 161 | public void onServiceDisconnected(ComponentName name) { 162 | mBflScanBinder = null; 163 | } 164 | }; 165 | 166 | /** 167 | * Broadcast receiver of BLE device scan service. 168 | * 169 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 170 | */ 171 | private final BroadcastReceiver mBflScanBroadcastReceiver = new BroadcastReceiver() { 172 | @Override 173 | public void onReceive(Context context, Intent intent) { 174 | final String action = intent.getAction(); 175 | 176 | String macAddress = intent.getStringExtra(BflDeviceScanService.EXTRA_BFL_MAC_ADDRESS_DATA); 177 | String deviceName = intent.getStringExtra(BflDeviceScanService.EXTRA_BFL_DEVICE_NAME_DATA); 178 | int rssi = intent.getIntExtra(BflDeviceScanService.EXTRA_BFL_RSSI_DATA, 0); 179 | 180 | if (action != null) { 181 | if (BflDeviceScanService.ACTION_BFL_SCAN_DATA.equals(action)) { 182 | if (sLeDeviceListAdapter != null) { 183 | try { 184 | sLeDeviceListAdapter.addDevice(macAddress, deviceName, rssi); 185 | sLeDeviceListAdapter.notifyDataSetChanged(); 186 | } catch (Exception e) { 187 | e.printStackTrace(); 188 | } 189 | } 190 | 191 | // If a user app doesn't use above list adapter, 192 | // use below BLE device information callback to use on a user app. 193 | if (mScannedCallback != null) { 194 | mScannedCallback.onDeviceInfo(macAddress, deviceName, rssi); 195 | } 196 | } else if (BflDeviceScanService.ACTION_BFL_SCAN_STATE_DATA.equals(action)) { 197 | if (mScanning ^ intent.getBooleanExtra(BflDeviceScanService.EXTRA_BFL_SCAN_STATE_DATA, false)) { 198 | mScanning = intent.getBooleanExtra(BflDeviceScanService.EXTRA_BFL_SCAN_STATE_DATA, false); 199 | 200 | if (mScanningCallback != null) { 201 | mScanningCallback.onScanningState(mScanning); 202 | } 203 | } 204 | } 205 | } else { 206 | Log.e(BLE_FOTA_TAG, "Device scanner broadcast data is NULL."); 207 | } 208 | } 209 | }; 210 | 211 | /** 212 | * BLE FOTA scan service connection. 213 | * Create service connection & start scanning. 214 | * 215 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 216 | */ 217 | public void connectScanSvc() { 218 | mScanServiceIntent = new Intent(mContext, BflDeviceScanService.class); 219 | // BLE FOTA Library uses daemon(local) background service using startService method to run independently 220 | // & remote service using bindService method to communicate by AIDL. 221 | mContext.startService(mScanServiceIntent); 222 | mContext.bindService(mScanServiceIntent, mBflScanSvcConnection, mContext.BIND_ADJUST_WITH_ACTIVITY); 223 | } 224 | 225 | /** 226 | * BLE FOTA Service disconnection. 227 | * 228 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 229 | * @see kr.co.sevencore.blefotalib.BflUtil 230 | */ 231 | public void disconnectScanSvc() { 232 | if (BflUtil.isServiceRunning(mContext, BflDeviceScanService.class)) { 233 | try { 234 | mContext.unbindService(mBflScanSvcConnection); 235 | mContext.stopService(mScanServiceIntent); 236 | mBflScanBinder = null; 237 | } catch (Exception e) { 238 | e.printStackTrace(); 239 | } 240 | } 241 | } 242 | 243 | /** 244 | * Customize scanning period. 245 | * The period is have to be set before execution of scanInit method. 246 | * 247 | * @param period is scanning time. 248 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 249 | */ 250 | public void setScanPeriod(long period) { 251 | mScanPeriodFlag = true; 252 | 253 | if (mBflScanBinder != null) { 254 | try { 255 | mBflScanBinder.setScanPeriod(period); 256 | } catch (Exception e) { 257 | e.printStackTrace(); 258 | } 259 | } 260 | } 261 | 262 | /** 263 | * Start scanning BLE devices. 264 | * Default scan period is 10 seconds. 265 | * 266 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 267 | */ 268 | public void startScanning() { 269 | if (sLeDeviceListAdapter != null) { 270 | sLeDeviceListAdapter.clear(); 271 | } 272 | 273 | if (mBflScanBinder != null) { 274 | disconnectScanSvc(); 275 | } 276 | 277 | if(!BflUtil.isServiceRunning(mContext, BflDeviceScanService.class)) { 278 | connectScanSvc(); 279 | setScanningState(false); 280 | } 281 | } 282 | 283 | /** 284 | * Start scanning BLE devices with scanning period customized. 285 | * 286 | * @param period is scanning period. 287 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 288 | */ 289 | public void startScanning(long period) { 290 | if (sLeDeviceListAdapter != null) { 291 | sLeDeviceListAdapter.clear(); 292 | } 293 | 294 | if (mBflScanBinder != null) { 295 | disconnectScanSvc(); 296 | } 297 | 298 | if(!BflUtil.isServiceRunning(mContext, BflDeviceScanService.class)) { 299 | mScanPeriodFlag = true; 300 | mScanPeriod = period; 301 | connectScanSvc(); 302 | setScanPeriod(mScanPeriod); 303 | setScanningState(false); 304 | } 305 | } 306 | 307 | /** 308 | * Stop scanning BLE devices. 309 | * 310 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 311 | */ 312 | public void stopScanning() { 313 | if (mBflScanBinder != null) { 314 | try { 315 | mBflScanBinder.setScanState(false); 316 | } catch (RemoteException e) { 317 | e.printStackTrace(); 318 | } 319 | disconnectScanSvc(); 320 | } 321 | setScanningState(true); 322 | } 323 | 324 | /** 325 | * Register broadcast receiver. 326 | * 327 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 328 | */ 329 | public void registerBflScanReceiver() { 330 | mContext.registerReceiver(mBflScanBroadcastReceiver, makeStateUpdateIntentFilter()); 331 | } 332 | 333 | /** 334 | * Unregister broadcast receiver. 335 | * 336 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 337 | */ 338 | public void unregisterBflScanReceiver() { 339 | try { 340 | mContext.unregisterReceiver(mBflScanBroadcastReceiver); 341 | } catch (Exception e) { 342 | e.printStackTrace(); 343 | } 344 | } 345 | 346 | /** 347 | * Update scanning state. 348 | * 349 | * @param state is BLE device scan state enabled or disabled. 350 | */ 351 | public void setScanningState(boolean state) { 352 | mScanning = state; 353 | } 354 | 355 | /** 356 | * Intent filter for BflDeviceScanService. 357 | * ACTION_SCAN_DATA: BLE device information. 358 | * ACTION_SCAN_STATE_DATA: Current scan status. 359 | * 360 | * @return intentFilter including ACTIONS. 361 | */ 362 | private static IntentFilter makeStateUpdateIntentFilter() { 363 | final IntentFilter intentFilter = new IntentFilter(); 364 | intentFilter.addAction(BflDeviceScanService.ACTION_BFL_SCAN_DATA); 365 | intentFilter.addAction(BflDeviceScanService.ACTION_BFL_SCAN_STATE_DATA); 366 | return intentFilter; 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflFwDownloadService.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.app.Service; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | import android.os.AsyncTask; 9 | import android.os.IBinder; 10 | import android.os.PowerManager; 11 | import android.os.RemoteException; 12 | import android.util.Log; 13 | 14 | import org.xmlpull.v1.XmlPullParser; 15 | import org.xmlpull.v1.XmlPullParserFactory; 16 | 17 | import java.io.BufferedInputStream; 18 | import java.io.File; 19 | import java.io.FileOutputStream; 20 | import java.io.InputStream; 21 | import java.io.OutputStream; 22 | import java.net.HttpURLConnection; 23 | import java.net.URL; 24 | 25 | import kr.co.sevencore.blefotalib.BflCodeList.DownloadCode; 26 | 27 | /** 28 | * BflFwDownloadService.java 29 | * BLE FOTA Library Firmware Download service. 30 | * This service downloads the firmware data from the firmware managing server. 31 | * 32 | * Debugging mode: 33 | * - sDeviceAddress = intent.getStringExtra("MAC_ADDRESS"); is disabled. 34 | * - Firmware saved directory is changed. 35 | * -> Internal directory (disabled): dir = getDir(sProductName, Context.MODE_PRIVATE); dirPath = dir.getAbsolutePath() + "/" + fileName; 36 | * -> External storage for debugging: dirPath = "/storage/sdcard0/Download/" + fileName; 37 | * 38 | * !Notice: 39 | * - Insert your server URL. (FIRMWARE_MANAGING_SERVER_URL) 40 | * - Insert server DB account ID. (FIRMWARE_MANAGING_SERVER_SERVER_ACCOUNT_ID) 41 | * - Insert server DB passwd. (FIRMWARE_MANAGING_SERVER_ACCOUNT_PWD) 42 | * 43 | * 2015 SEVENCORE Co., Ltd. 44 | * 45 | * @author Jungwoo Park 46 | * @version 1.0.0 47 | * @since 2015-06-12 48 | * @see kr.co.sevencore.blefotalib.BflFwDownloader 49 | * @see kr.co.sevencore.blefotalib.IBflFwDownloadSvc 50 | */ 51 | public class BflFwDownloadService extends Service { 52 | private final static String BLE_FOTA_TAG = BflFwDownloadService.class.getSimpleName(); 53 | 54 | private ServerConnection mServerConnection; 55 | private FirmwareDownload mFirmwareDownload; 56 | private int mSvcId; 57 | 58 | private static PowerManager sPowerManager; 59 | private static PowerManager.WakeLock sCpuWakeLock = null; 60 | 61 | private static String sDeviceAddress;// MAC address of the device. 62 | private static String sProductName; // Product name of the device. 63 | private static String sFirmwareName; // Firmware file name. 64 | private static String sVersion; // Firmware version information from the server. 65 | private static String sUrl; // Firmware download URL. 66 | 67 | private final static String FIRMWARE_MANAGING_SERVER_URL = ""; //Insert your server URL. 68 | private final static String FIRMWARE_MANAGING_SERVER_DIR = "BLE_FIRMWARE/"; 69 | private final static String FIRMWARE_MANAGING_SERVER_GETPRODUCTNAME = "getproductname.php"; 70 | private final static String FIRMWARE_MANAGING_SERVER_GETURL = "geturl.php"; 71 | private final static String FIRMWARE_MANAGING_SERVER_GETVERSION = "getversion.php"; 72 | private final static String FIRMWARE_MANAGING_SERVER_SERVER_ACCOUNT_ID = "dbuser=account_ID"; // Insert server DB account ID. 73 | private final static String FIRMWARE_MANAGING_SERVER_ACCOUNT_PWD = "dbpasswd=pwd"; // Insert server DB passwd. 74 | private final static String FIRMWARE_MANAGING_SERVER_MAC_ID_IDENTIFIER = "?mac="; 75 | 76 | public final static String ACTION_ERROR_UNKNOWN_DEVICE = 77 | "kr.co.sevencore.ble.fota.lib.download.ACTION_ERROR_UNKNOWN_DEVICE"; 78 | public final static String ACTION_ERROR_FIRMWARE_DATA_INTEGRITY = 79 | "kr.co.sevencore.ble.fota.lib.download.ACTION_ERROR_FIRMWARE_DATA_INTEGRITY"; 80 | public final static String ACTION_PRODUCT_NAME = 81 | "kr.co.sevencore.ble.fota.lib.download.ACTION_PRODUCT_NAME"; 82 | public final static String ACTION_FIRMWARE_VERSION = 83 | "kr.co.sevencore.ble.fota.lib.download.ACTION_FIRMWARE_VERSION"; 84 | public final static String ACTION_FIRMWARE_URL = 85 | "kr.co.sevencore.ble.fota.lib.download.ACTION_FIRMWARE_URL"; 86 | public final static String ACTION_FIRMWARE_DOWNLOAD_START = 87 | "kr.co.sevencore.ble.fota.lib.download.ACTION_FIRMWARE_DOWNLOAD_START"; 88 | public final static String ACTION_FIRMWARE_DOWNLOADING = 89 | "kr.co.sevencore.ble.fota.lib.download.ACTION_FIRMWARE_DOWNLOADING"; 90 | public final static String ACTION_FIRMWARE_DOWNLOAD_FINISH = 91 | "kr.co.sevencore.ble.fota.lib.download.ACTION_FINISHING_DOWNLOAD"; 92 | public final static String EXTRA_DATA = 93 | "kr.co.sevencore.ble.fota.lib.download.ACTION_EXTRA_DATA"; 94 | 95 | 96 | public BflFwDownloadService() {} 97 | 98 | @Override 99 | public IBinder onBind(Intent intent) { 100 | if (intent.getStringExtra("MAC_ADDRESS") != null) { 101 | sDeviceAddress = intent.getStringExtra("MAC_ADDRESS"); 102 | //sDeviceAddress = "80:EA:CA:00:00:01"; // Used for debugging. 103 | } 104 | 105 | // Get the product name of the device. 106 | getFirmwareInfo(FIRMWARE_MANAGING_SERVER_URL + 107 | FIRMWARE_MANAGING_SERVER_DIR + FIRMWARE_MANAGING_SERVER_GETPRODUCTNAME + 108 | FIRMWARE_MANAGING_SERVER_MAC_ID_IDENTIFIER + sDeviceAddress); 109 | 110 | return mBflFwDownloadBinder; 111 | } 112 | 113 | IBflFwDownloadSvc.Stub mBflFwDownloadBinder = new IBflFwDownloadSvc.Stub() { 114 | 115 | /** 116 | * Check initial state of network to download firmware data from the server. 117 | * 118 | * @return true, if mobile or WiFi network is available. 119 | * @throws RemoteException 120 | */ 121 | @Override 122 | public boolean initDownloader() throws RemoteException { 123 | // TODO: Classifying a kind of available networks to response to charged network usage. 124 | // Default network check item: Mobile communication & WiFi. 125 | ConnectivityManager connectivityManager; 126 | NetworkInfo networkInfo; 127 | 128 | connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 129 | networkInfo = connectivityManager.getActiveNetworkInfo(); 130 | 131 | if (networkInfo != null) { 132 | if (networkInfo.getType() == 0 || networkInfo.getType() == 1) { 133 | // Type 0: Mobile communication network enabled. 134 | // Type 1: WiFi network enabled. 135 | return true; 136 | } 137 | } 138 | 139 | Log.e(BLE_FOTA_TAG, "Network is not able to use"); 140 | return false; 141 | } 142 | 143 | /** 144 | * Get URL information of firmware managing server to update the firmware of the device. 145 | * TODO: This method have to be located in sandbox in the future because of the server related information. 146 | * 147 | * @throws RemoteException 148 | */ 149 | @Override 150 | public void getFirmwareUrl() throws RemoteException { 151 | getFirmwareInfo(FIRMWARE_MANAGING_SERVER_URL + 152 | FIRMWARE_MANAGING_SERVER_DIR + FIRMWARE_MANAGING_SERVER_GETURL + 153 | FIRMWARE_MANAGING_SERVER_MAC_ID_IDENTIFIER + sDeviceAddress); 154 | } 155 | 156 | @Override 157 | public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, 158 | double aDouble, String aString) {} 159 | }; 160 | 161 | @Override 162 | public boolean onUnbind(Intent intent) { 163 | return super.onUnbind(intent); 164 | } 165 | 166 | /** 167 | * Make a firmware file name by firmware version information. 168 | * 169 | * @param firmwareName is a firmware file name. 170 | */ 171 | private void makeFirmwareFileName(String firmwareName) { 172 | String sFirmwareFileExt = ".BIN"; // Firmware file name extension. 173 | sFirmwareName = firmwareName + sFirmwareFileExt; 174 | } 175 | 176 | /** 177 | * Get firmware information to be updated. 178 | * 179 | * @param serverUrl is the URL of firmware managing server to be able to request firmware information. 180 | */ 181 | private void getFirmwareInfo(String serverUrl) { 182 | mServerConnection = new ServerConnection(); 183 | mServerConnection.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, serverUrl); 184 | } 185 | 186 | /** 187 | * Get firmware data. 188 | * 189 | * @param downloadUrl is the URL of firmware managing server to get firmware data. 190 | */ 191 | private void getFirmware(String downloadUrl) { 192 | mFirmwareDownload = new FirmwareDownload(); 193 | mFirmwareDownload.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, downloadUrl); 194 | } 195 | 196 | /** 197 | * Update firmware download progress information. 198 | * 199 | * @param action used for filtering. 200 | */ 201 | private void broadcastUpdate(final String action) { 202 | final Intent fwDownloadIntent = new Intent(action); 203 | sendBroadcast(fwDownloadIntent); 204 | } 205 | 206 | /** 207 | * Update firmware data information. 208 | * 209 | * @param action used for filtering. 210 | * @param info is firmware data information. 211 | */ 212 | private void broadcastUpdate(final String action, final String info) { 213 | final Intent fwDownloadIntent = new Intent(action); 214 | fwDownloadIntent.putExtra(EXTRA_DATA, info); 215 | sendBroadcast(fwDownloadIntent); 216 | } 217 | 218 | /** 219 | * Update firmware data information. 220 | * 221 | * @param action used for filtering. 222 | * @param info is firmware data information. 223 | */ 224 | private void broadcastUpdate(final String action, final int info) { 225 | final Intent fwDownloadIntent = new Intent(action); 226 | fwDownloadIntent.putExtra(EXTRA_DATA, info); 227 | sendBroadcast(fwDownloadIntent); 228 | } 229 | 230 | @Override 231 | public int onStartCommand(Intent intent, int flags, int startId) { 232 | mSvcId = startId; 233 | 234 | Log.d(BLE_FOTA_TAG, "onStartCommand service start ID: " + mSvcId); 235 | return START_REDELIVER_INTENT; 236 | } 237 | 238 | @Override 239 | public void onCreate() { 240 | super.onCreate(); 241 | 242 | // CPU wake lock is used to keep service running. 243 | // CPU wake lock is managed by each service(especially scan service) or the main application. 244 | sPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 245 | sCpuWakeLock = sPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "FIRMWARE_DOWNLOAD"); 246 | sCpuWakeLock.acquire(); 247 | } 248 | 249 | /** 250 | * FOTA is managed by firmware managing server. 251 | * Server connection is used to get information to manage a firmware version. 252 | * 253 | * @see kr.co.sevencore.blefotalib.BflFwDownloader 254 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 255 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService.FirmwareDownload 256 | */ 257 | private class ServerConnection extends AsyncTask { 258 | 259 | private final static int SERVER_CONNECTION_TIMEOUT = 3000; 260 | 261 | private String mEncoding = "UTF-8"; 262 | private int mEventType; 263 | 264 | private String mTagMac = "mac"; 265 | private String mTagProduct = "product"; 266 | private String mTagFwVer = "firmwareversion"; 267 | private String mTagFwUrl = "firmwareurl"; 268 | 269 | @Override 270 | protected String doInBackground(String... urls) { 271 | try { 272 | InputStream inputStream = null; 273 | 274 | URL url = new URL(urls[0]); 275 | HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 276 | 277 | if (httpURLConnection != null) { 278 | httpURLConnection.setConnectTimeout(SERVER_CONNECTION_TIMEOUT); 279 | httpURLConnection.setUseCaches(false); 280 | 281 | // Numeric status code HttpURLConnection.HTTP_OK: 200 282 | if (httpURLConnection.getResponseCode() == 200) { 283 | inputStream = url.openStream(); 284 | } 285 | httpURLConnection.disconnect(); 286 | } 287 | 288 | return parseData(inputStream); 289 | 290 | } catch (Exception e) { 291 | mServerConnection.cancel(true); 292 | Log.e(BLE_FOTA_TAG, "Firmware information download error."); 293 | 294 | if (sCpuWakeLock != null) { 295 | sCpuWakeLock.release(); 296 | sCpuWakeLock = null; 297 | } 298 | 299 | e.printStackTrace(); 300 | } 301 | return null; 302 | } 303 | 304 | /** 305 | * Get firmware information by parsing XML data. 306 | * 307 | * @param inputStream is XML data. 308 | * @return firmware information. 309 | */ 310 | private String parseData(InputStream inputStream) { 311 | try { 312 | XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance(); 313 | XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser(); 314 | xmlPullParser.setInput(inputStream, mEncoding); 315 | mEventType = xmlPullParser.getEventType(); 316 | 317 | while (mEventType != XmlPullParser.END_DOCUMENT) { 318 | if (isCancelled()) { 319 | Log.i(BLE_FOTA_TAG, "AsyncTask of ServerConnection is cancelled."); 320 | //break; // "break" is replaced with "return null". 321 | return null; 322 | } 323 | 324 | switch (mEventType) { 325 | case XmlPullParser.START_TAG: 326 | String startTag = xmlPullParser.getName(); 327 | 328 | if (startTag.equals(mTagMac)) { 329 | mEventType = xmlPullParser.next(); 330 | 331 | if (sDeviceAddress.equals(xmlPullParser.getText())) { 332 | sDeviceAddress = xmlPullParser.getText(); 333 | Log.i(BLE_FOTA_TAG, "Device MAC address: " + sDeviceAddress); 334 | 335 | } else { 336 | return DownloadCode.SERVER_CONN_ERROR_UNKNOWN_DEVICE.getCode(); 337 | } 338 | 339 | } else if (startTag.equals(mTagProduct)) { 340 | mEventType = xmlPullParser.next(); 341 | sProductName = xmlPullParser.getText(); 342 | 343 | broadcastUpdate(ACTION_PRODUCT_NAME, sProductName); 344 | Log.d(BLE_FOTA_TAG, "Product name from the server: " + sProductName); 345 | 346 | return DownloadCode.SERVER_CONN_PROCESS_CHECKING_VERSION.getCode(); 347 | 348 | } else if (startTag.equals(mTagFwVer)) { 349 | mEventType = xmlPullParser.next(); 350 | sVersion = xmlPullParser.getText(); 351 | 352 | broadcastUpdate(ACTION_FIRMWARE_VERSION, sVersion); 353 | Log.d(BLE_FOTA_TAG, "Firmware version from the server: " + sVersion); 354 | 355 | return DownloadCode.SERVER_CONN_PROCESS_GETTING_VERSION_NAME.getCode(); 356 | 357 | } else if (startTag.equals(mTagFwUrl)) { 358 | mEventType = xmlPullParser.next(); 359 | sUrl = xmlPullParser.getText(); 360 | 361 | broadcastUpdate(ACTION_FIRMWARE_URL, sUrl); 362 | Log.d(BLE_FOTA_TAG, "Firmware download URL: " + sUrl); 363 | 364 | return DownloadCode.SERVER_CONN_PROCESS_GETTING_FIRMWARE.getCode(); 365 | } 366 | break; 367 | 368 | case XmlPullParser.END_TAG: 369 | mEventType = xmlPullParser.next(); 370 | break; 371 | } 372 | mEventType = xmlPullParser.next(); 373 | } 374 | } catch (Exception e) { 375 | if (sCpuWakeLock != null) { 376 | sCpuWakeLock.release(); 377 | sCpuWakeLock = null; 378 | } 379 | e.printStackTrace(); 380 | } 381 | return null; 382 | } 383 | 384 | protected void onPostExecute(String result) { 385 | Log.d(BLE_FOTA_TAG, 386 | "onPostExecute result code of ServerConnection AsyncTask: " + result); 387 | 388 | if (result != null) { 389 | if (DownloadCode.SERVER_CONN_ERROR_UNKNOWN_DEVICE.getCode().equals(result)) { 390 | broadcastUpdate(ACTION_ERROR_UNKNOWN_DEVICE); 391 | 392 | } else if (DownloadCode.SERVER_CONN_PROCESS_CHECKING_VERSION.getCode().equals(result)) { 393 | // Get the new version information of the device. 394 | getFirmwareInfo(FIRMWARE_MANAGING_SERVER_URL + 395 | FIRMWARE_MANAGING_SERVER_DIR + FIRMWARE_MANAGING_SERVER_GETVERSION + 396 | FIRMWARE_MANAGING_SERVER_MAC_ID_IDENTIFIER + sDeviceAddress); 397 | 398 | } else if (DownloadCode.SERVER_CONN_PROCESS_GETTING_VERSION_NAME.getCode().equals(result)) { 399 | makeFirmwareFileName(sVersion); 400 | 401 | } else if (DownloadCode.SERVER_CONN_PROCESS_GETTING_FIRMWARE.getCode().equals(result)) { 402 | getFirmware(sUrl + sFirmwareName); 403 | } 404 | } else { 405 | stopSelf(mSvcId); 406 | } 407 | } 408 | } 409 | 410 | /** 411 | * Firmware download from the server. 412 | * 413 | * @see kr.co.sevencore.blefotalib.BflFwDownloader 414 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 415 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService.ServerConnection 416 | */ 417 | private class FirmwareDownload extends AsyncTask { 418 | @Override 419 | protected String doInBackground(String... urls) { 420 | try { 421 | URL url = new URL(urls[0]); 422 | HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); 423 | httpURLConnection.connect(); 424 | 425 | File file, dir; 426 | String dirPath, fileName; 427 | int fileSize; 428 | int count; 429 | int progressCount = 0; 430 | 431 | fileSize = httpURLConnection.getContentLength(); 432 | broadcastUpdate(ACTION_FIRMWARE_DOWNLOAD_START, fileSize); 433 | Log.i(BLE_FOTA_TAG, "Firmware data size from the server: " + fileSize); 434 | 435 | fileName = new File(urls[0]).getName(); 436 | Log.i(BLE_FOTA_TAG, "Firmware file name from the server: " + fileName); 437 | 438 | //dir = getDir(sProductName, Context.MODE_PRIVATE); 439 | //dirPath = dir.getAbsolutePath() + "/" + fileName; 440 | dirPath = "/storage/sdcard0/Download/" + fileName; // Used for debugging. 441 | Log.d(BLE_FOTA_TAG, "Firmware data stored at: " + dirPath); 442 | 443 | file = new File(dirPath); 444 | 445 | // If existing file is valid, finish firmware download task. 446 | // If existing file is invalid, delete file and resume firmware download process. 447 | if (file.exists()) { 448 | if (!checkIntegrity(file, fileSize)) { 449 | file.delete(); 450 | broadcastUpdate(ACTION_ERROR_FIRMWARE_DATA_INTEGRITY); 451 | Log.d(BLE_FOTA_TAG, "New firmware file is invalid data."); 452 | } else { 453 | //file.delete(); // Used for debug. Unconditionally delete file & download firmware data. 454 | httpURLConnection.disconnect(); 455 | return DownloadCode.FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD.getCode(); 456 | } 457 | } 458 | 459 | InputStream firmwareInputData = new BufferedInputStream(url.openStream()); 460 | OutputStream firmwareOutputData = new FileOutputStream(file); 461 | 462 | if (fileSize > 0) { 463 | byte data[] = new byte[fileSize]; 464 | 465 | try { 466 | while ((count = firmwareInputData.read(data)) != -1) { 467 | if (isCancelled()) { 468 | Log.i(BLE_FOTA_TAG, "AsyncTask of FirmwareDownload is cancelled."); 469 | break; // "break" is replaced with "return null". 470 | //return null; 471 | } 472 | firmwareOutputData.write(data, 0, count); 473 | 474 | // Used for notifying progress. 475 | progressCount += count; 476 | broadcastUpdate(ACTION_FIRMWARE_DOWNLOADING, progressCount); 477 | } 478 | } catch (Exception e) { 479 | Log.e(BLE_FOTA_TAG, "Firmware download error."); 480 | e.printStackTrace(); 481 | } 482 | } 483 | 484 | firmwareOutputData.flush(); 485 | firmwareOutputData.close(); 486 | firmwareInputData.close(); 487 | httpURLConnection.disconnect(); 488 | return DownloadCode.FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD.getCode(); 489 | 490 | } catch (Exception e) { 491 | if (sCpuWakeLock != null) { 492 | sCpuWakeLock.release(); 493 | sCpuWakeLock = null; 494 | } 495 | e.printStackTrace(); 496 | } 497 | return null; 498 | } 499 | 500 | /** 501 | * Check download file integrity. 502 | * TODO: checkIntegrity method is going to be replaced with checksum check method. 503 | * 504 | * @param file is firmware data. 505 | * @param fileSize is firmware data size information from the remote server. 506 | * @return true, if the firmware data integrity is valid. 507 | */ 508 | private boolean checkIntegrity(File file, int fileSize) { 509 | return (fileSize == (int) file.length()); 510 | } 511 | 512 | protected void onPostExecute(String result) { 513 | if (result != null && DownloadCode.FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD.getCode().equals(result)) { 514 | broadcastUpdate(ACTION_FIRMWARE_DOWNLOAD_FINISH); 515 | 516 | if (sCpuWakeLock != null) { 517 | sCpuWakeLock.release(); 518 | sCpuWakeLock = null; 519 | } 520 | } else { 521 | stopSelf(mSvcId); 522 | } 523 | } 524 | } 525 | 526 | @Override 527 | public void onDestroy() { 528 | super.onDestroy(); 529 | 530 | if (mServerConnection != null) { 531 | mServerConnection.cancel(true); 532 | } 533 | 534 | if (mFirmwareDownload != null) { 535 | mFirmwareDownload.cancel(true); 536 | } 537 | 538 | if (sCpuWakeLock != null) { 539 | sCpuWakeLock.release(); 540 | sCpuWakeLock = null; 541 | } 542 | } 543 | } 544 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflFwDownloader.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.content.ServiceConnection; 9 | import android.os.IBinder; 10 | import android.os.RemoteException; 11 | import android.util.Log; 12 | 13 | import kr.co.sevencore.blefotalib.BflCodeList.DownloadCode; 14 | 15 | /** 16 | * BflFwDownloader.java 17 | * BLE FOTA Library Firmware Download. 18 | * 19 | * 2015 SEVENCORE Co., Ltd. 20 | * 21 | * @author Jungwoo Park 22 | * @version 1.0.0 23 | * @since 2015-06-12 24 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 25 | * @see kr.co.sevencore.blefotalib.IBflFwDownloadSvc 26 | */ 27 | public class BflFwDownloader { 28 | private final static String BLE_FOTA_TAG = BflFwDownloader.class.getSimpleName(); 29 | 30 | private Context mContext; 31 | 32 | public static IBflFwDownloadSvc sBflDownloadBinder; // Firmware data download service AIDL. 33 | private Intent mDownloadServiceIntent; 34 | private String mAddress; // The target device MAC address. 35 | 36 | private boolean mDownloadProgressFlag = false; // Prevent creation of download progress AsyncTask. 37 | 38 | private OnDownloadSvcInit mDownloadSvcInitCallback; // Service initialization result of the firmware download callback. 39 | private OnFirmwareInfoListener mFirmwareInfoCallback; // New firmware data information of the target device. 40 | private OnProgressCountListener mProgressCountCallback; // Firmware download progress information callback. 41 | 42 | 43 | public BflFwDownloader(Context context) { 44 | mContext = context; 45 | } 46 | 47 | /** 48 | * OnDownloadSvcInit interface is used to get the result of firmware download service initialization. 49 | */ 50 | public interface OnDownloadSvcInit { 51 | /** 52 | * Initialization firmware download service by checking network available status of the smart device. 53 | * 54 | * @param initResult true: The smart device network is available. 55 | * false: The smart device network is not available. 56 | */ 57 | void onDownloadSvcInit(boolean initResult); 58 | } 59 | 60 | /** 61 | * OnFirmwareInfoListener interface is used to get firmware download related data. 62 | * If a main application needs a firmware information of the server, 63 | * use onFirmwareInfoListener method. 64 | */ 65 | public interface OnFirmwareInfoListener { 66 | /** 67 | * The firmware related information of the device which is going to be updated from the server. 68 | * 69 | * ============== Code Table ============== 70 | * Code | Information 71 | * ---------------------------------------- 72 | * 7000 | Unknown device error 73 | * 7100 | Product name information 74 | * 7102 | Firmware version information 75 | * 7103 | Firmware download URL information 76 | * 7200 | Invalid firmware data error 77 | * 78 | * @param code is a identifier of each information. 79 | * @param info is a firmware and device information. 80 | * @see kr.co.sevencore.blefotalib.BflCodeList.DownloadCode 81 | */ 82 | void onFirmwareInfoListener(String code, String info); 83 | } 84 | 85 | /** 86 | * OnProgressCountListener interface is used to get a firmware download status. 87 | * If a main application shows firmware download progress, 88 | * use onProgressCountListener. 89 | */ 90 | public interface OnProgressCountListener { 91 | /** 92 | * This method is used to update firmware download progress. 93 | * When firmware download is started, send firmware data size information. 94 | * After firmware data size updated, send received data size. 95 | * Progress count starts at "0" when firmware download is started, 96 | * and it is set to "0" when firmware download is finished. 97 | * Each state sends below the information. 98 | * 99 | * ============================= State Table ============================== 100 | * Code | State | Information 101 | * ------------------------------------------------------------------------ 102 | * 7200 | FIRMWARE_DOWNLOAD_PROCESS_STARTING_DOWNLOAD | Firmware data size 103 | * 7201 | FIRMWARE_DOWNLOAD_PROGRESSING | Received data size 104 | * 7203 | FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD | 0 (Initialization) 105 | * 106 | * @param state is a progression of firmware data download. 107 | * @param size is a firmware data size or received data size. 108 | * @see kr.co.sevencore.blefotalib.BflCodeList.DownloadCode 109 | */ 110 | void onProgressCountListener(String state, int size); 111 | } 112 | 113 | /** 114 | * Save a callback object to mDownloadSvcInitCallback. 115 | * 116 | * @see kr.co.sevencore.blefotalib.BflFwDownloader.OnDownloadSvcInit 117 | */ 118 | public void setOnDownloadSvcInit(OnDownloadSvcInit callback) { 119 | mDownloadSvcInitCallback = callback; 120 | } 121 | 122 | /** 123 | * Save a callback object to mFirmwareInfoCallback. 124 | * 125 | * @see kr.co.sevencore.blefotalib.BflFwDownloader.OnFirmwareInfoListener 126 | */ 127 | public void setOnFirmwareInfoListener(OnFirmwareInfoListener callback) { 128 | mFirmwareInfoCallback = callback; 129 | } 130 | 131 | /** 132 | * Save a callback object to mProgressCountCallback. 133 | * 134 | * @see kr.co.sevencore.blefotalib.BflFwDownloader.OnProgressCountListener 135 | */ 136 | public void setOnProgressCountListener(OnProgressCountListener callback) { 137 | mProgressCountCallback = callback; 138 | } 139 | 140 | /** 141 | * Create an object to implement a service connection interface. 142 | * 143 | * @see kr.co.sevencore.blefotalib.IBflFwDownloadSvc 144 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 145 | */ 146 | private final ServiceConnection mBflDownloadSvcConnection = new ServiceConnection() { 147 | @Override 148 | public void onServiceConnected(ComponentName name, IBinder service) { 149 | sBflDownloadBinder = IBflFwDownloadSvc.Stub.asInterface(service); 150 | boolean initResult = true; 151 | 152 | try { 153 | if (!sBflDownloadBinder.initDownloader()) { 154 | initResult = false; 155 | Log.e(BLE_FOTA_TAG, "Unable to initialize firmware downloader"); 156 | } 157 | 158 | if (mDownloadSvcInitCallback != null) { 159 | mDownloadSvcInitCallback.onDownloadSvcInit(initResult); 160 | } 161 | } catch (RemoteException e) { 162 | e.printStackTrace(); 163 | } 164 | } 165 | 166 | @Override 167 | public void onServiceDisconnected(ComponentName name) { 168 | sBflDownloadBinder = null; 169 | } 170 | }; 171 | 172 | /** 173 | * Broadcast receiver of firmware data download service. 174 | * 175 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 176 | * @see kr.co.sevencore.blefotalib.BflUtil 177 | */ 178 | private final BroadcastReceiver mBflDownloadBroadcastReceiver = new BroadcastReceiver() { 179 | @Override 180 | public void onReceive(Context context, Intent intent) { 181 | final String action = intent.getAction(); 182 | 183 | if (action != null) { 184 | if (BflFwDownloadService.ACTION_ERROR_UNKNOWN_DEVICE.equals(action)) { 185 | if (mFirmwareInfoCallback != null) { 186 | mFirmwareInfoCallback.onFirmwareInfoListener( 187 | BflCodeList.DownloadCode.SERVER_CONN_ERROR_UNKNOWN_DEVICE.getCode(), null 188 | ); 189 | } 190 | Log.e(BLE_FOTA_TAG, "Bluetooth Smart device is not registered with the server."); 191 | 192 | } else if (BflFwDownloadService.ACTION_ERROR_FIRMWARE_DATA_INTEGRITY.equals(action)) { 193 | if (mFirmwareInfoCallback != null) { 194 | mFirmwareInfoCallback.onFirmwareInfoListener( 195 | DownloadCode.FIRMWARE_DOWNLOAD_ERROR_INVALIDATE_DATA.getCode(), null 196 | ); 197 | } 198 | Log.e(BLE_FOTA_TAG, "Existing firmware data is invalid."); 199 | 200 | } else if (BflFwDownloadService.ACTION_PRODUCT_NAME.equals(action)) { 201 | String productName = intent.getStringExtra(BflFwDownloadService.EXTRA_DATA); 202 | 203 | if (mFirmwareInfoCallback != null) { 204 | mFirmwareInfoCallback.onFirmwareInfoListener( 205 | DownloadCode.SERVER_CONN_PROCESS_PRODUCT_INFO.getCode(), 206 | productName 207 | ); 208 | } 209 | Log.d(BLE_FOTA_TAG, "Device name: " + productName); 210 | 211 | } else if (BflFwDownloadService.ACTION_FIRMWARE_VERSION.equals(action)) { 212 | String firmwareNewVersion = intent.getStringExtra(BflFwDownloadService.EXTRA_DATA); 213 | 214 | // Compare the device firmware version and the server firmware version. 215 | Intent versionInfoIntent = new Intent(BflFwVerChecker.ACTION_SERVER_VERSION); 216 | versionInfoIntent.putExtra(BflFwVerChecker.VERSION_INFO, firmwareNewVersion); 217 | versionInfoIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 218 | context.sendBroadcast(versionInfoIntent); 219 | 220 | if (mFirmwareInfoCallback != null) { 221 | mFirmwareInfoCallback.onFirmwareInfoListener( 222 | DownloadCode.SERVER_CONN_PROCESS_GETTING_VERSION_NAME.getCode(), 223 | firmwareNewVersion 224 | ); 225 | } 226 | Log.d(BLE_FOTA_TAG, "Firmware version from the server: " + firmwareNewVersion); 227 | 228 | } else if (BflFwDownloadService.ACTION_FIRMWARE_URL.equals(action)) { 229 | String downloadUrl = intent.getStringExtra(BflFwDownloadService.EXTRA_DATA); 230 | 231 | if (mFirmwareInfoCallback != null) { 232 | mFirmwareInfoCallback.onFirmwareInfoListener( 233 | DownloadCode.SERVER_CONN_PROCESS_URL_INFO.getCode(), 234 | downloadUrl 235 | ); 236 | } 237 | Log.d(BLE_FOTA_TAG, "Firmware download URL: " + downloadUrl); 238 | 239 | } else if (BflFwDownloadService.ACTION_FIRMWARE_DOWNLOAD_START.equals(action)) { 240 | int dataSize = intent.getIntExtra(BflFwDownloadService.EXTRA_DATA, 0); 241 | 242 | if (!mDownloadProgressFlag) { 243 | mDownloadProgressFlag = true; 244 | 245 | if (mProgressCountCallback != null) { 246 | mProgressCountCallback.onProgressCountListener( 247 | DownloadCode.FIRMWARE_DOWNLOAD_PROCESS_STARTING_DOWNLOAD.getCode(), 248 | dataSize 249 | ); 250 | } 251 | Log.d(BLE_FOTA_TAG, "Firmware download started. Firmware file size: " + dataSize); 252 | } 253 | } else if (BflFwDownloadService.ACTION_FIRMWARE_DOWNLOADING.equals(action)) { 254 | int transmissionSize = intent.getIntExtra(BflFwDownloadService.EXTRA_DATA, 0); 255 | 256 | if (mDownloadProgressFlag) { 257 | if (mProgressCountCallback != null) { 258 | mProgressCountCallback.onProgressCountListener( 259 | DownloadCode.FIRMWARE_DOWNLOAD_PROGRESSING.getCode(), 260 | transmissionSize 261 | ); 262 | } 263 | Log.d(BLE_FOTA_TAG, "Firmware download transmission size: " + transmissionSize); 264 | } 265 | 266 | } else if (BflFwDownloadService.ACTION_FIRMWARE_DOWNLOAD_FINISH.equals(action)) { 267 | if (mDownloadProgressFlag) { 268 | mDownloadProgressFlag = false; 269 | // Initialize the reception data size. 270 | if (mProgressCountCallback != null) { 271 | mProgressCountCallback.onProgressCountListener( 272 | DownloadCode.FIRMWARE_DOWNLOAD_PROCESS_FINISHING_DOWNLOAD.getCode(), 0 273 | ); 274 | } 275 | } 276 | // Finish firmware download service. 277 | disconnectDownloadSvc(); 278 | } 279 | } else { 280 | Log.e(BLE_FOTA_TAG, "Firmware downloader broadcast data is NULL."); 281 | } 282 | } 283 | }; 284 | 285 | /** 286 | * BLE FOTA firmware download service connection. 287 | * Create service connection & download firmware from the sever. 288 | * 289 | * @param address is the device MAC address. 290 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 291 | */ 292 | public void connectDownloadSvc(String address) { 293 | mAddress = address; 294 | 295 | mDownloadServiceIntent = new Intent(mContext, BflFwDownloadService.class); 296 | mDownloadServiceIntent.putExtra("MAC_ADDRESS", mAddress); 297 | // BLE FOTA Library uses a daemon(local) background service using startService method to run independently 298 | // & a remote service using bindService method to communicate by AIDL. 299 | mContext.startService(mDownloadServiceIntent); 300 | mContext.bindService(mDownloadServiceIntent, mBflDownloadSvcConnection, mContext.BIND_ADJUST_WITH_ACTIVITY); 301 | } 302 | 303 | /** 304 | * BLE FOTA firmware download service disconnection. 305 | * 306 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 307 | * @see kr.co.sevencore.blefotalib.BflUtil 308 | */ 309 | public void disconnectDownloadSvc() { 310 | if (BflUtil.isServiceRunning(mContext, BflFwDownloadService.class)) { 311 | try { 312 | mContext.unbindService(mBflDownloadSvcConnection); 313 | mContext.stopService(mDownloadServiceIntent); 314 | sBflDownloadBinder = null; 315 | } catch (Exception e) { 316 | e.printStackTrace(); 317 | } 318 | } 319 | } 320 | 321 | /** 322 | * Register broadcast receiver. 323 | * 324 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 325 | */ 326 | public void registerBflDownloadReceiver() { 327 | mContext.registerReceiver(mBflDownloadBroadcastReceiver, makeDownloadProgressIntentFilter()); 328 | } 329 | 330 | /** 331 | * Unregister broadcast receiver. 332 | * 333 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 334 | */ 335 | public void unregisterBflDownloadReceiver() { 336 | try { 337 | mContext.unregisterReceiver(mBflDownloadBroadcastReceiver); 338 | } catch (Exception e) { 339 | e.printStackTrace(); 340 | } 341 | } 342 | 343 | /** 344 | * Intent filter for BflFwDownloadService. 345 | * ACTION_ERROR_UNKNOWN_DEVICE: The device is not registered on the server. 346 | * ACTION_ERROR_FIRMWARE_DATA_INTEGRITY: Firmware data integrity check from the server. 347 | * ACTION_PRODUCT_NAME: The device name from the server. 348 | * ACTION_FIRMWARE_VERSION: Firmware version information from the server. 349 | * ACTION_FIRMWARE_URL: Firmware download URL information. 350 | * ACTION_FIRMWARE_DOWNLOAD_START: Firmware download started. It is used to notify file size. 351 | * ACTION_FIRMWARE_DOWNLOADING: Firmware is downloading. It is used to update download progress. 352 | * ACTION_FIRMWARE_DOWNLOAD_FINISH: Firmware download finished. 353 | * 354 | * @return Intent filter. 355 | */ 356 | private static IntentFilter makeDownloadProgressIntentFilter() { 357 | final IntentFilter intentFilter = new IntentFilter(); 358 | intentFilter.addAction(BflFwDownloadService.ACTION_ERROR_UNKNOWN_DEVICE); 359 | intentFilter.addAction(BflFwDownloadService.ACTION_ERROR_FIRMWARE_DATA_INTEGRITY); 360 | intentFilter.addAction(BflFwDownloadService.ACTION_PRODUCT_NAME); 361 | intentFilter.addAction(BflFwDownloadService.ACTION_FIRMWARE_VERSION); 362 | intentFilter.addAction(BflFwDownloadService.ACTION_FIRMWARE_URL); 363 | intentFilter.addAction(BflFwDownloadService.ACTION_FIRMWARE_DOWNLOAD_START); 364 | intentFilter.addAction(BflFwDownloadService.ACTION_FIRMWARE_DOWNLOADING); 365 | intentFilter.addAction(BflFwDownloadService.ACTION_FIRMWARE_DOWNLOAD_FINISH); 366 | intentFilter.addAction(BflFwDownloadService.EXTRA_DATA); 367 | return intentFilter; 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflFwUploader.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.IntentFilter; 8 | import android.content.ServiceConnection; 9 | import android.os.IBinder; 10 | import android.os.RemoteException; 11 | import android.util.Log; 12 | import android.widget.SimpleExpandableListAdapter; 13 | 14 | import java.io.File; 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | 18 | import kr.co.sevencore.blefotalib.BflCodeList.UploadCode; 19 | import kr.co.sevencore.blefotalib.BflCodeList.ServiceIdxCode; 20 | import kr.co.sevencore.blefotalib.BflCodeList.CharacteristicFotaIdxCode; 21 | import kr.co.sevencore.blefotalib.BflCodeList.CharacteristicDeviceInfoIdxCode; 22 | 23 | /** 24 | * BflFwUploader.java 25 | * BLE FOTA Library Firmware Upload. 26 | * 27 | * 2015 SEVENCORE Co., Ltd. 28 | * 29 | * @author Jungwoo Park 30 | * @version 1.0.0 31 | * @since 2015-04-08 32 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 33 | * @see kr.co.sevencore.blefotalib.IBflFwUploadSvc 34 | * TODO.. Apply flag value - 00: The BLE device is rebooted by the old firmware, 01: The BLE device is rebooted by the new firmware. 35 | */ 36 | public class BflFwUploader { 37 | private final static String BLE_FOTA_TAG = BflFwUploader.class.getSimpleName(); 38 | 39 | public IBflFwUploadSvc mBflUploadBinder; // Firmware data upload service AIDL. 40 | private Intent mUploadServiceIntent; 41 | private String mAddress; // The target device MAC address. 42 | 43 | private Context mContext; 44 | 45 | private static String sFirmwareCurrentVersion; // Current target device(BLE server) firmware version. 46 | private static String sFirmwareNewVersion; // If another firmware data exists at the target device(BLE server), return firmware version of the target device, 47 | private static String sFirmwareVersion; // Selected firmware version at the smart device(BLE client). 48 | 49 | private static String sFilePath; // Selected firmware data file path. 50 | private static int sLeftConnCnt = 0; // Left firmware data count. 51 | private static int sSequenceNumber = -1; // Sequence number starts at 0. 52 | 53 | private static String sFirmwareDataStatus; // Firmware data integrity status. 54 | private static String sFirmwareStatus; // Firmware software status. 55 | 56 | private static byte sFirmwareUpgradeTypeFlag = 0; // Flag 0 : Normal upgrade | Flag 1 : Forced upgrade 57 | private static byte sResetFlag = 1; // Flag 0: Not reset | Flag 1: Reset 58 | 59 | private static String sManufacturerName; // Device manufacturer name. 60 | private static String sModelNumber; // Device model number. 61 | private static String sSerialNumber; // Device serial number. 62 | 63 | private static String sExtraData; // Extra data information by read or write characteristic. 64 | 65 | private static boolean sInitAutoProgressFlag = false; // Initialization for FOTA automation flag. 66 | private static boolean sAutoProgressFlag = false; // Firmware upgrade automation flag. 67 | 68 | private final String NORMAL = "0"; // Firmware data check & status normal status. 69 | private final String VALIDATE = "1"; // Firmware data validate status. 70 | private final String INVALIDATE = "2"; // Firmware data invalidate status. 71 | private final String SUCCESSFUL = "1"; // Firmware status successful status. 72 | private final String ABNORMAL_FINISH = "2"; // Firmware status abnormal finish status. 73 | 74 | private OnUploadSvcInit mUploadSvcInitCallback; // Service initialization result of the firmware upload callback. 75 | private OnConnectionState mConnectionCallback; // BLE connection status callback. 76 | private OnErrorStateListener mErrorStateCallback; // Error state for connection callback. 77 | private OnUpdateGattServiceListener mUpdateGattServiceCallback; // GATT service list adapter callback. 78 | private OnDeviceInfoListener mDeviceInfoCallback; // Device and firmware status related information in doing FOTA callback. 79 | 80 | 81 | public BflFwUploader() {} 82 | 83 | public BflFwUploader(Context context) { 84 | mContext = context; 85 | } 86 | 87 | /** 88 | * OnUploadSvcInit interface is used to get result of firmware upload service initialization. 89 | */ 90 | public interface OnUploadSvcInit { 91 | /** 92 | * Initialization using BLE of the smart device. 93 | * 94 | * @param initResult true: All of BLE related feature is normal state. 95 | * false: Unable to initialize BLE relate feature. 96 | */ 97 | void onUploadSvcInit(boolean initResult); 98 | } 99 | 100 | /** 101 | * OnConnectionState interface is used to get state of connection. 102 | * If a main application needs to get state of BLE connection state, 103 | * use onConnectionState method. 104 | */ 105 | public interface OnConnectionState { 106 | /** 107 | * Get BLE connection state. 108 | * 109 | * @param state true: connected 110 | * false: disconnected. 111 | */ 112 | void onConnectionState(boolean state); 113 | } 114 | 115 | /** 116 | * OnErrorStateListener interface is used to notify error state. 117 | * If a main application needs to get the error state of Bluetooth GATT or device information to used for connection, 118 | * use onErrorStateListener. 119 | */ 120 | public interface OnErrorStateListener { 121 | /** 122 | * Get error state. 123 | * 124 | * @param state true: Error state. 125 | * false: Normal state. 126 | */ 127 | void onErrorStateListener(boolean state); 128 | } 129 | 130 | /** 131 | * OnUpdateGattServiceListener interface is used to get GATT service adapter. 132 | * If a main application needs to show service list by expandable list adapter, 133 | * use onUpdateGattServiceListener method. 134 | */ 135 | public interface OnUpdateGattServiceListener { 136 | /** 137 | * Get GATT service list adapter of the target device. 138 | * 139 | * @param gattServiceAdapter includes GATT services lists. 140 | */ 141 | void onUpdateGattServiceListener(SimpleExpandableListAdapter gattServiceAdapter); 142 | } 143 | 144 | /** 145 | * OnDeviceInfoListener interface is used to get firmware upgrade progress related data of the target device. 146 | * If a main application needs a firmware upgrade progress related information, 147 | * use onDeviceInfoListener method. 148 | */ 149 | public interface OnDeviceInfoListener { 150 | /** 151 | * Used to get string information data of firmware upgrade progress. 152 | * 153 | * @param code is a progress identifier of firmware upgrade progress. 154 | * @param data is the information related each progress state. 155 | */ 156 | void onDeviceInfoListener(String code, String data); 157 | 158 | /** 159 | * Used to get integer value of sequence number about firmware upgrade. 160 | * 161 | * @param code is a progress identifier of firmware upgrade progress. 162 | * @param data is the sequence number value. 163 | */ 164 | void onDataSequenceNumberListener(String code, int data); 165 | } 166 | 167 | /** 168 | * Save a callback object to mUploadSvcInitCallback. 169 | * 170 | * @see kr.co.sevencore.blefotalib.BflFwUploader.OnUploadSvcInit 171 | */ 172 | public void setOnUploadSvcInit(OnUploadSvcInit callback) { 173 | mUploadSvcInitCallback = callback; 174 | } 175 | 176 | /** 177 | * Save a callback object to mConnectionCallback. 178 | * 179 | * @see kr.co.sevencore.blefotalib.BflFwUploader.OnConnectionState 180 | */ 181 | public void setOnConnectionState(OnConnectionState callback) { 182 | mConnectionCallback = callback; 183 | } 184 | 185 | /** 186 | * Save a callback object to mErrorStateCallback. 187 | * 188 | * @see kr.co.sevencore.blefotalib.BflFwUploader.OnErrorStateListener 189 | */ 190 | public void setOnErrorStateListener(OnErrorStateListener callback) { 191 | mErrorStateCallback = callback; 192 | } 193 | 194 | /** 195 | * Save a callback object to mUpdateGattServiceCallback. 196 | * 197 | * @see kr.co.sevencore.blefotalib.BflFwUploader.OnUpdateGattServiceListener 198 | */ 199 | public void setOnUpdateGattServiceListener(OnUpdateGattServiceListener callback) { 200 | mUpdateGattServiceCallback = callback; 201 | } 202 | 203 | /** 204 | * Save a callback object to mDeviceInfoCallback. 205 | * 206 | * @see kr.co.sevencore.blefotalib.BflFwUploader.OnDeviceInfoListener 207 | */ 208 | public void setOnDeviceInfoListener(OnDeviceInfoListener callback) { 209 | mDeviceInfoCallback = callback; 210 | } 211 | 212 | /** 213 | * Get the new firmware version information. 214 | * 215 | * @return The new firmware version information. 216 | */ 217 | public String getFirmwareVersion() { 218 | return sFirmwareVersion; 219 | } 220 | 221 | /** 222 | * Get the file path of the firmware data. 223 | * 224 | * @return The path of firmware data location. 225 | */ 226 | public String getFilePath() { 227 | return sFilePath; 228 | } 229 | 230 | /** 231 | * Get the firmware upgrade type. 232 | * 233 | * @return The firmware upgrade type flag. 234 | */ 235 | public byte getFirmwareUpgradeType() { 236 | return sFirmwareUpgradeTypeFlag; 237 | } 238 | 239 | /** 240 | * Set the new firmware version. 241 | * 242 | * @param version is extracted from the file name to be a new firmware version. 243 | */ 244 | public void setFirmwareVersion(String version) { 245 | sFirmwareVersion = version; 246 | } 247 | 248 | /** 249 | * Set the file path of the firmware data. 250 | * 251 | * @param path is the location of the firmware data. 252 | */ 253 | public void setFilePath(String path) { 254 | sFilePath = path; 255 | } 256 | 257 | /** 258 | * Set the firmware upgrade type. 259 | * 260 | * @param type is firmware upgrade type. 261 | */ 262 | public void setFirmwareUpgradeType(byte type) { 263 | sFirmwareUpgradeTypeFlag = type; 264 | } 265 | 266 | /** 267 | * Create an object to implement a service connection interface. 268 | * The firmware upload service updates the firmware of the BLE device. 269 | * 270 | * @see kr.co.sevencore.blefotalib.IBflFwUploadSvc 271 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 272 | */ 273 | private final ServiceConnection mBflUploadSvcConnection = new ServiceConnection() { 274 | @Override 275 | public void onServiceConnected(ComponentName name, IBinder service) { 276 | mBflUploadBinder = IBflFwUploadSvc.Stub.asInterface(service); 277 | boolean initResult = true; 278 | 279 | try { 280 | if (!mBflUploadBinder.initUploader()) { 281 | initResult = false; 282 | Log.e(BLE_FOTA_TAG, "Unable to initialize Bluetooth."); 283 | } 284 | 285 | try { 286 | Thread.sleep(500); 287 | } catch (InterruptedException e) { 288 | e.printStackTrace(); 289 | } 290 | 291 | if (mUploadSvcInitCallback != null) { 292 | mUploadSvcInitCallback.onUploadSvcInit(initResult); 293 | } 294 | 295 | try { 296 | Thread.sleep(1000); 297 | } catch (InterruptedException e) { 298 | e.printStackTrace(); 299 | } 300 | 301 | if(mAddress != null) { 302 | mBflUploadBinder.connect(mAddress); 303 | } else { 304 | Log.e(BLE_FOTA_TAG, "Connection creation failed because MAC address value is NULL."); 305 | } 306 | } catch (RemoteException e) { 307 | e.printStackTrace(); 308 | } 309 | } 310 | 311 | @Override 312 | public void onServiceDisconnected(ComponentName name) { 313 | mBflUploadBinder = null; 314 | } 315 | }; 316 | 317 | /** 318 | * Broadcast receiver of firmware upload service. 319 | * Handle various events fired by the Service. 320 | * ACTION_GATT_CONNECTED: Connected to a GATT server. 321 | * ACTION_GATT_DISCONNECTED: Disconnected from a GATT server. 322 | * ACTION_GATT_SERVICES_DISCOVERED: GATT services Discovered. 323 | * ACTION_GATT_DATA_AVAILABLE: Update GATT services & characteristics list to be used to do FOTA. 324 | * ACTION_DATA_AVAILABLE: Received data from the device. A result of read or notification operations. 325 | * ACTION_DATA_WRITABLE: Transmitting data from client device. A result of write operation. 326 | * 327 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 328 | */ 329 | private final BroadcastReceiver mBflUploadBroadcastReceiver = new BroadcastReceiver() { 330 | @Override 331 | public void onReceive(Context context, Intent intent) { 332 | final String action = intent.getAction(); 333 | 334 | if (action != null) { 335 | if (BflFwUploadService.ERROR_LOST_GATT.equals(action)) { 336 | 337 | if (mErrorStateCallback != null) { 338 | mErrorStateCallback.onErrorStateListener(true); 339 | } 340 | } else if (BflFwUploadService.ERROR_LOST_DEVICE_INFORMATION.equals(action)) { 341 | 342 | if (mErrorStateCallback != null) { 343 | mErrorStateCallback.onErrorStateListener(true); 344 | } 345 | } else if (BflFwUploadService.ACTION_GATT_CONNECTED.equals(action)) { 346 | Log.i(BLE_FOTA_TAG, "The device is connected."); 347 | 348 | // Update connection state by the callback. 349 | if (mConnectionCallback != null) { 350 | mConnectionCallback.onConnectionState(true); 351 | } 352 | } else if (BflFwUploadService.ACTION_GATT_DISCONNECTED.equals(action)) { 353 | Log.i(BLE_FOTA_TAG, "The device is disconnected."); 354 | 355 | initializeValue(); 356 | 357 | // Update connection state by the callback. 358 | if (mConnectionCallback != null) { 359 | mConnectionCallback.onConnectionState(false); 360 | } 361 | } else if (BflFwUploadService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { 362 | try { 363 | // Update GATT services to do FOTA. 364 | mBflUploadBinder.updateGatt(); 365 | } catch (RemoteException e) { 366 | e.printStackTrace(); 367 | } 368 | } else if (BflFwUploadService.ACTION_GATT_DATA_AVAILABLE.equals(action)) { 369 | // Show all the supported services and characteristics on the user interface. 370 | if (mUpdateGattServiceCallback != null) { 371 | mUpdateGattServiceCallback.onUpdateGattServiceListener( 372 | updateGattServicesAdapter( 373 | (ArrayList>) intent.getExtras(). 374 | getSerializable(BflFwUploadService.GATT_SERVICE_DATA_AVAILABLE), 375 | (ArrayList>>) intent.getExtras(). 376 | getSerializable(BflFwUploadService.GATT_CHARACTERISTIC_DATA_AVAILABLE) 377 | ) 378 | ); 379 | } 380 | 381 | if (sInitAutoProgressFlag) { 382 | // Firmware version characteristic read property execution. 383 | executeReadFirmwareCurrentVersion(); 384 | } 385 | 386 | } else if (BflFwUploadService.ACTION_FIRMWARE_CURRENT_VERSION_AVAILABLE.equals(action)) { 387 | sFirmwareCurrentVersion = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 388 | 389 | // Compare the device firmware version and the server firmware version. 390 | Intent versionInfoIntent = new Intent(BflFwVerChecker.ACTION_TARGET_VERSION); 391 | versionInfoIntent.putExtra(BflFwVerChecker.VERSION_INFO, sFirmwareCurrentVersion); 392 | versionInfoIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); 393 | context.sendBroadcast(versionInfoIntent); 394 | 395 | if (sInitAutoProgressFlag) { 396 | // Firmware new version characteristic read property execution. 397 | executeReadFirmwareNewVersion(); 398 | } 399 | 400 | if (mDeviceInfoCallback != null) { 401 | mDeviceInfoCallback.onDeviceInfoListener( 402 | UploadCode.DEVICE_FIRMWARE_CURRENT_VERSION.getCode(), 403 | sFirmwareCurrentVersion 404 | ); 405 | } 406 | Log.d(BLE_FOTA_TAG, "Current firmware version: " + sFirmwareCurrentVersion); 407 | 408 | } else if (BflFwUploadService.ACTION_FIRMWARE_NEW_VERSION_AVAILABLE.equals(action)) { 409 | sFirmwareNewVersion = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 410 | 411 | final String defaultVersion = "00-00-00"; 412 | 413 | if (sInitAutoProgressFlag) { 414 | // Manufacturer name characteristic read property execution. 415 | executeReadManufacturerName(); 416 | } 417 | 418 | // If you want to manage firmware version information 419 | // between a new firmware data which is going to be transmitted 420 | // and a existing new firmware data which exists on the device, 421 | // use below conditional statement. 422 | if (sFirmwareNewVersion.equals(defaultVersion)) { 423 | if (mDeviceInfoCallback != null) { 424 | mDeviceInfoCallback.onDeviceInfoListener( 425 | UploadCode.DEVICE_FIRMWARE_NEW_VERSION_EMPTINESS.getCode(), 426 | sFirmwareNewVersion 427 | ); 428 | } 429 | } else { 430 | if (mDeviceInfoCallback != null) { 431 | mDeviceInfoCallback.onDeviceInfoListener( 432 | UploadCode.DEVICE_FIRMWARE_NEW_VERSION_EXISTENCE.getCode(), 433 | sFirmwareNewVersion 434 | ); 435 | } 436 | } 437 | Log.d(BLE_FOTA_TAG, "New firmware version: " + sFirmwareNewVersion); 438 | 439 | } else if (BflFwUploadService.ACTION_SEQUENCE_NUMBER_AVAILABLE.equals(action)) { 440 | if (sAutoProgressFlag && (intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null)) { 441 | sSequenceNumber = Integer.parseInt(intent.getStringExtra(BflFwUploadService.EXTRA_DATA)); 442 | 443 | // Check the existing file size to resume transmitting the firmware data 444 | // or checking firmware data integrity. 445 | if (!checkSequence(sFilePath, sSequenceNumber)) { 446 | try { 447 | mBflUploadBinder.executeWriteFirmwareData( 448 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 449 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_DATA.getCode(), 450 | sFilePath, sSequenceNumber); 451 | } catch (RemoteException e) { 452 | e.printStackTrace(); 453 | } 454 | } else { 455 | try { 456 | mBflUploadBinder.executeWriteChecksumData( 457 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 458 | CharacteristicFotaIdxCode.CHARACTERISTIC_CHECKSUM_DATA.getCode(), 459 | sFilePath); 460 | } catch (RemoteException e) { 461 | e.printStackTrace(); 462 | } 463 | } 464 | 465 | if (mDeviceInfoCallback != null) { 466 | mDeviceInfoCallback.onDataSequenceNumberListener( 467 | UploadCode.DEVICE_FIRMWARE_AVAILABLE_SEQUENCE_NUMBER.getCode(), 468 | sSequenceNumber 469 | ); 470 | } 471 | } 472 | Log.d(BLE_FOTA_TAG, "Data sequence number of the device: " + sSequenceNumber); 473 | 474 | } else if (BflFwUploadService.ACTION_FIRMWARE_DATA_CHECK_AVAILABLE.equals(action)) { 475 | if (sAutoProgressFlag && (intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null)) { 476 | sFirmwareDataStatus = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 477 | 478 | // Firmware data check flag value - NORMAL: 0, VALIDATE: 1, INVALIDATE: 2 479 | switch (sFirmwareDataStatus) { 480 | case NORMAL: 481 | if (mDeviceInfoCallback != null) { 482 | mDeviceInfoCallback.onDeviceInfoListener( 483 | UploadCode.DEVICE_FIRMWARE_DATA_STATUS_NORMAL.getCode(), 484 | sFirmwareDataStatus 485 | ); 486 | } 487 | Log.i(BLE_FOTA_TAG, "Firmware data has not been verified yet."); 488 | break; 489 | 490 | case VALIDATE: 491 | try { 492 | mBflUploadBinder.executeWriteFirmwareUpgradeType( 493 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 494 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_UPGRADE_TYPE.getCode(), 495 | sFirmwareUpgradeTypeFlag 496 | ); 497 | } catch (RemoteException e) { 498 | e.printStackTrace(); 499 | } 500 | 501 | if (mDeviceInfoCallback != null) { 502 | mDeviceInfoCallback.onDeviceInfoListener( 503 | UploadCode.DEVICE_FIRMWARE_DATA_STATUS_VALID.getCode(), 504 | sFirmwareDataStatus 505 | ); 506 | } 507 | Log.i(BLE_FOTA_TAG, "Firmware data validated."); 508 | break; 509 | 510 | case INVALIDATE: 511 | sAutoProgressFlag = false; 512 | 513 | if (mDeviceInfoCallback != null) { 514 | mDeviceInfoCallback.onDeviceInfoListener( 515 | UploadCode.DEVICE_FIRMWARE_DATA_STATUS_INVALID.getCode(), 516 | sFirmwareDataStatus 517 | ); 518 | } 519 | Log.i(BLE_FOTA_TAG, "Firmware data invalidated"); 520 | break; 521 | } 522 | } 523 | } else if (BflFwUploadService.ACTION_FIRMWARE_STATUS_AVAILABLE.equals(action)) { 524 | if (sAutoProgressFlag && (intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null)) { 525 | sFirmwareStatus = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 526 | 527 | // Firmware upgrade status flag value - NORMAL: 0, SUCCESSFUL: 1, ABNORMAL FINISH: 2 528 | switch (sFirmwareStatus) { 529 | case NORMAL: 530 | if (mDeviceInfoCallback != null) { 531 | mDeviceInfoCallback.onDeviceInfoListener( 532 | UploadCode.DEVICE_FIRMWARE_STATUS_NORMAL.getCode(), 533 | sFirmwareStatus 534 | ); 535 | } 536 | Log.i(BLE_FOTA_TAG, "Upgrade is not over yet."); 537 | break; 538 | 539 | case SUCCESSFUL: 540 | try { 541 | mBflUploadBinder.executeWriteReset( 542 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 543 | CharacteristicFotaIdxCode.CHARACTERISTIC_RESET.getCode(), 544 | sResetFlag 545 | ); 546 | Log.i(BLE_FOTA_TAG, "Target device reset now."); 547 | } catch (RemoteException e) { 548 | e.printStackTrace(); 549 | } 550 | 551 | if (mDeviceInfoCallback != null) { 552 | mDeviceInfoCallback.onDeviceInfoListener( 553 | UploadCode.DEVICE_FIRMWARE_STATUS_SUCCESSFUL_FINISH.getCode(), 554 | sFirmwareStatus 555 | ); 556 | } 557 | Log.i(BLE_FOTA_TAG, "Firmware upgrade finished successfully."); 558 | break; 559 | 560 | case ABNORMAL_FINISH: 561 | sAutoProgressFlag = false; 562 | 563 | if (mDeviceInfoCallback != null) { 564 | mDeviceInfoCallback.onDeviceInfoListener( 565 | UploadCode.DEVICE_FIRMWARE_STATUS_ABNORMAL_FINISH.getCode(), 566 | sFirmwareStatus 567 | ); 568 | } 569 | Log.i(BLE_FOTA_TAG, "Firmware upgrade finished abnormally."); 570 | break; 571 | } 572 | } 573 | } else if (BflFwUploadService.ACTION_MANUFACTURER_NAME_AVAILABLE.equals(action)) { 574 | sManufacturerName = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 575 | 576 | if (sInitAutoProgressFlag) { 577 | try { 578 | Thread.sleep(700); 579 | } catch (InterruptedException e) { 580 | e.printStackTrace(); 581 | } 582 | // Model number characteristic read property execution. 583 | executeReadModelNumber(); 584 | } 585 | 586 | if (mDeviceInfoCallback != null) { 587 | mDeviceInfoCallback.onDeviceInfoListener( 588 | UploadCode.DEVICE_INFORMATION_MANUFACTURER_NAME.getCode(), 589 | sManufacturerName 590 | ); 591 | } 592 | } else if (BflFwUploadService.ACTION_MODEL_NUMBER_AVAILABLE.equals(action)) { 593 | sModelNumber = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 594 | 595 | if (sInitAutoProgressFlag) { 596 | try { 597 | Thread.sleep(700); 598 | } catch (InterruptedException e) { 599 | e.printStackTrace(); 600 | } 601 | // Serial number characteristic read property execution. 602 | executeReadSerialNumber(); 603 | } 604 | 605 | if (mDeviceInfoCallback != null) { 606 | mDeviceInfoCallback.onDeviceInfoListener( 607 | UploadCode.DEVICE_INFORMATION_MODEL_NUMBER.getCode(), 608 | sModelNumber 609 | ); 610 | } 611 | } else if (BflFwUploadService.ACTION_SERIAL_NUMBER_AVAILABLE.equals(action)) { 612 | sSerialNumber = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 613 | 614 | if (mDeviceInfoCallback != null) { 615 | mDeviceInfoCallback.onDeviceInfoListener( 616 | UploadCode.DEVICE_INFORMATION_SERIAL_NUMBER.getCode(), 617 | sSerialNumber 618 | ); 619 | } 620 | } else if (BflFwUploadService.ACTION_DATA_AVAILABLE.equals(action)) { 621 | sExtraData = intent.getStringExtra(BflFwUploadService.EXTRA_DATA); 622 | 623 | if (mDeviceInfoCallback != null) { 624 | mDeviceInfoCallback.onDeviceInfoListener( 625 | UploadCode.DEVICE_EXTRA_DATA.getCode(), sExtraData 626 | ); 627 | } 628 | Log.d(BLE_FOTA_TAG, "Read extra data: " + sExtraData); 629 | 630 | } else if (BflFwUploadService.ACTION_FIRMWARE_NEW_VERSION_WRITABLE.equals(action)) { 631 | if (sAutoProgressFlag && intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null) { 632 | try { 633 | mBflUploadBinder.executeWriteFirmwareData( 634 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 635 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_DATA.getCode(), 636 | sFilePath, sSequenceNumber); 637 | Log.d(BLE_FOTA_TAG, "Execute firmware upgrade. Starting firmware data transmission."); 638 | } catch (RemoteException e) { 639 | e.printStackTrace(); 640 | } 641 | } 642 | Log.d(BLE_FOTA_TAG, "Transmit a new version information to the target device."); 643 | 644 | } else if (BflFwUploadService.ACTION_FIRMWARE_DATA_WRITABLE.equals(action)) { 645 | sLeftConnCnt = Integer.parseInt(intent.getStringExtra(BflFwUploadService.EXTRA_DATA)); 646 | 647 | if (sAutoProgressFlag && (sLeftConnCnt == 0)) { 648 | try { 649 | mBflUploadBinder.executeWriteChecksumData( 650 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 651 | CharacteristicFotaIdxCode.CHARACTERISTIC_CHECKSUM_DATA.getCode(), 652 | sFilePath); 653 | Log.d(BLE_FOTA_TAG, "Generate & transmit checksum data."); 654 | } catch (RemoteException e) { 655 | e.printStackTrace(); 656 | } 657 | } 658 | 659 | if (mDeviceInfoCallback != null) { 660 | mDeviceInfoCallback.onDataSequenceNumberListener( 661 | UploadCode.DEVICE_FIRMWARE_DATA_LEFT_COUNT.getCode(), 662 | sLeftConnCnt 663 | ); 664 | } 665 | Log.d(BLE_FOTA_TAG, "Left data count: " + sLeftConnCnt); 666 | 667 | } else if (BflFwUploadService.ACTION_SEQUENCE_NUMBER_WRITABLE.equals(action)) { 668 | int writableSequenceNumber = Integer.parseInt(intent.getStringExtra(BflFwUploadService.EXTRA_DATA)); 669 | 670 | if (mDeviceInfoCallback != null) { 671 | mDeviceInfoCallback.onDataSequenceNumberListener( 672 | UploadCode.DEVICE_FIRMWARE_WRITABLE_SEQUENCE_NUMBER.getCode(), 673 | writableSequenceNumber 674 | ); 675 | } 676 | Log.i(BLE_FOTA_TAG, "Sequence number is " + writableSequenceNumber); 677 | 678 | } else if (BflFwUploadService.ACTION_CHECKSUM_DATA_WRITABLE.equals(action)) { 679 | if (sAutoProgressFlag && (intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null)) { 680 | executeReadFirmwareDataCheck(); 681 | } 682 | Log.d(BLE_FOTA_TAG, "Transmitting checksum data."); 683 | 684 | } else if (BflFwUploadService.ACTION_FIRMWARE_UPGRADE_TYPE_WRITABLE.equals(action)) { 685 | if (sAutoProgressFlag && (intent.getStringExtra(BflFwUploadService.EXTRA_DATA) != null)) { 686 | executeReadFirmwareStatus(); 687 | } 688 | 689 | switch (sFirmwareUpgradeTypeFlag) { 690 | case 0: 691 | if (mDeviceInfoCallback != null) { 692 | mDeviceInfoCallback.onDeviceInfoListener( 693 | UploadCode.DEVICE_FIRMWARE_UPGRADE_TYPE_NORMAL.getCode(), 694 | "0" 695 | ); 696 | } 697 | break; 698 | 699 | case 1: 700 | if (mDeviceInfoCallback != null) { 701 | mDeviceInfoCallback.onDeviceInfoListener( 702 | UploadCode.DEVICE_FIRMWARE_UPGRADE_TYPE_FORCED.getCode(), 703 | "1" 704 | ); 705 | } 706 | break; 707 | } 708 | Log.d(BLE_FOTA_TAG, "Firmware update type: " + sFirmwareUpgradeTypeFlag); 709 | 710 | } else if (BflFwUploadService.ACTION_RESET_WRITABLE.equals(action)) { 711 | if (mDeviceInfoCallback != null) { 712 | mDeviceInfoCallback.onDeviceInfoListener( 713 | UploadCode.DEVICE_FIRMWARE_RESET.getCode(), 714 | null 715 | ); 716 | } 717 | Log.d(BLE_FOTA_TAG, "The target device is reset"); 718 | 719 | } else if (BflFwUploadService.ACTION_DATA_WRITABLE.equals(action)) { 720 | if (mDeviceInfoCallback != null) { 721 | mDeviceInfoCallback.onDeviceInfoListener( 722 | UploadCode.DEVICE_EXTRA_DATA.getCode(), 723 | intent.getStringExtra(BflFwUploadService.EXTRA_DATA) 724 | ); 725 | } 726 | } 727 | } else { 728 | Log.e(BLE_FOTA_TAG, "Firmware uploader broadcast data is NULL."); 729 | } 730 | } 731 | }; 732 | 733 | /** 734 | * BLE FOTA firmware upload service connection. 735 | * Create service connection. 736 | * 737 | * @param address is the device MAC address. 738 | * @param initAutoProgress is auto progress setting for initial value. 739 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 740 | */ 741 | public void connectUploadSvc(String address, boolean initAutoProgress) { 742 | mAddress = address; 743 | sInitAutoProgressFlag = initAutoProgress; 744 | 745 | mUploadServiceIntent = new Intent(mContext, BflFwUploadService.class); 746 | // BLE FOTA Library uses daemon(local) background service using startService method to run independently 747 | // & remote service using bindService method to communicate by AIDL. 748 | mContext.startService(mUploadServiceIntent); 749 | mContext.bindService(mUploadServiceIntent, mBflUploadSvcConnection, mContext.BIND_AUTO_CREATE); 750 | } 751 | 752 | /** 753 | * BLE FOTA firmware upload service disconnection. 754 | * 755 | * @see kr.co.sevencore.blefotalib.BflDeviceScanService 756 | * @see kr.co.sevencore.blefotalib.BflUtil 757 | */ 758 | public void disconnectUploadSvc() { 759 | sInitAutoProgressFlag = false; 760 | 761 | if (BflUtil.isServiceRunning(mContext, BflFwUploadService.class)) { 762 | try { 763 | mContext.unbindService(mBflUploadSvcConnection); 764 | mContext.stopService(mUploadServiceIntent); 765 | mBflUploadBinder = null; 766 | } catch (Exception e) { 767 | e.printStackTrace(); 768 | } 769 | } 770 | } 771 | 772 | /** 773 | * Create connection with the BLE device. 774 | * 775 | * @param address of the BLE device is used for creating connection. 776 | */ 777 | public void connect(String address) { 778 | if (mBflUploadBinder != null) { 779 | try { 780 | mBflUploadBinder.connect(address); 781 | } catch (RemoteException e) { 782 | e.printStackTrace(); 783 | } 784 | } 785 | } 786 | 787 | /** 788 | * Close connection with the BLE device. 789 | */ 790 | public void disconnect() { 791 | if (mBflUploadBinder != null) { 792 | try { 793 | mBflUploadBinder.disconnect(); 794 | } catch (RemoteException e) { 795 | e.printStackTrace(); 796 | } 797 | } 798 | } 799 | 800 | /** 801 | * After closing connection by disconnect method, 802 | * system resources have to be released properly by close method. 803 | */ 804 | public void close() { 805 | if (mBflUploadBinder != null) { 806 | try { 807 | mBflUploadBinder.close(); 808 | } catch (RemoteException e) { 809 | e.printStackTrace(); 810 | } 811 | } 812 | } 813 | 814 | /** 815 | * Register broadcast receiver. 816 | * 817 | * @param context is gettable from the caller application. 818 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 819 | */ 820 | public void registerBflUploadReceiver(Context context) { 821 | context.registerReceiver(mBflUploadBroadcastReceiver, makeGattUpdateIntentFilter()); 822 | } 823 | 824 | /** 825 | * Unregister broadcast receiver. 826 | * 827 | * @see kr.co.sevencore.blefotalib.BflFwDownloadService 828 | */ 829 | public void unregisterBflUploadReceiver() { 830 | try { 831 | mContext.unregisterReceiver(mBflUploadBroadcastReceiver); 832 | } catch (Exception e) { 833 | e.printStackTrace(); 834 | } 835 | } 836 | 837 | /** 838 | * Set FOTA progress automation flag. 839 | * 840 | * @param flag is boolean value to be set. 841 | */ 842 | public void setAutoProgressFlag(boolean flag) { 843 | sAutoProgressFlag = flag; 844 | } 845 | 846 | /** 847 | * Initialize FOTA progress related values. 848 | */ 849 | private void initializeValue() { 850 | sLeftConnCnt = 0; 851 | 852 | sSequenceNumber = -1; 853 | sFirmwareUpgradeTypeFlag = 0; 854 | } 855 | 856 | /** 857 | * Update GATT service adapter. 858 | * 859 | * @param gattServiceData is services list. 860 | * @param gattCharacteristicData is characteristics list. 861 | * @return GATT service adapter. 862 | * @see kr.co.sevencore.blefotalib.BflFwUploadService 863 | */ 864 | public SimpleExpandableListAdapter updateGattServicesAdapter( 865 | ArrayList> gattServiceData, ArrayList>> gattCharacteristicData) { 866 | SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter( 867 | mContext, 868 | gattServiceData, 869 | android.R.layout.simple_expandable_list_item_2, 870 | new String[] {BflCodeList.LIST_NAME, BflCodeList.LIST_UUID}, 871 | new int[] { android.R.id.text1, android.R.id.text2}, 872 | gattCharacteristicData, 873 | android.R.layout.simple_expandable_list_item_2, 874 | new String[] {BflCodeList.LIST_NAME, BflCodeList.LIST_UUID}, 875 | new int[] { android.R.id.text1, android.R.id.text2 } 876 | ); 877 | return gattServiceAdapter; 878 | } 879 | 880 | /** 881 | * Check more data is needed to be transmitted to the target device. 882 | * 883 | * @param filePath is the location that firmware data stored. 884 | * @param sequenceNumber is amount of data going to be transmitted. 885 | * @return true: More data is needed to be transmitted. 886 | * false: Firmware data transmission finished. 887 | */ 888 | private boolean checkSequence(String filePath, int sequenceNumber) { 889 | File firmwareFile = new File(filePath); 890 | long length = firmwareFile.length(); 891 | int sequence = sequenceNumber; 892 | int sendSize; 893 | 894 | if (sequence < -1) { 895 | sequence += 256; // Used for overflow. 896 | } 897 | 898 | if ((length % BflFwUploadService.PURE_EACH_CONN_DATA_SIZE) != 0) { 899 | sendSize = (sequence * BflFwUploadService.EACH_CONN_DATA_SIZE) 900 | + ((int) length % BflFwUploadService.PURE_EACH_CONN_DATA_SIZE); 901 | } else { 902 | sendSize = (sequence + 1) * BflFwUploadService.EACH_CONN_DATA_SIZE; 903 | } 904 | 905 | return (sendSize >= (int) length); 906 | } 907 | 908 | /** 909 | * Execute the specific BLE property. 910 | * 911 | * @param serviceIdx is index of services in adapter. 912 | * @param characteristicIdx is index of characteristics in adapter. 913 | * @return false: sAutoProgressFlag is disabled or BluetoothGattCharacteristic is null. 914 | */ 915 | public boolean executeProperty(int serviceIdx, int characteristicIdx) { 916 | if (!sAutoProgressFlag) { 917 | try { 918 | // Return true: onWriteCharacteristic | onReadCharacteristic | setCharacteristicNotification callback. 919 | return mBflUploadBinder.checkProperty(serviceIdx, characteristicIdx); 920 | } catch (RemoteException e) { 921 | e.printStackTrace(); 922 | } 923 | } 924 | return false; 925 | } 926 | 927 | /** 928 | * 18FF FOTA service. 929 | * 2AF0 Firmware version characteristic. 930 | * READ property function of FOTA profile. 931 | */ 932 | public void executeReadFirmwareCurrentVersion() { 933 | try { 934 | mBflUploadBinder.executeReadCharacteristic( 935 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 936 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_VERSION.getCode() 937 | ); 938 | } catch (RemoteException e) { 939 | e.printStackTrace(); 940 | } 941 | } 942 | 943 | /** 944 | * 18FF FOTA service. 945 | * 2AF1 Firmware new version characteristic 946 | * READ (| WRITE) property function of FOTA profile. 947 | */ 948 | public void executeReadFirmwareNewVersion() { 949 | try { 950 | mBflUploadBinder.executeReadCharacteristic( 951 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 952 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_NEW_VERSION.getCode() 953 | ); 954 | } catch (RemoteException e) { 955 | e.printStackTrace(); 956 | } 957 | } 958 | 959 | /** 960 | * 18FF FOTA service. 961 | * 2AF3 Sequence number characteristic. 962 | * READ property function of FOTA profile. 963 | */ 964 | public void executeReadSequenceNumber() { 965 | try { 966 | mBflUploadBinder.executeReadCharacteristic( 967 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 968 | CharacteristicFotaIdxCode.CHARACTERISTIC_SEQUENCE_NUMBER.getCode() 969 | ); 970 | } catch (RemoteException e) { 971 | e.printStackTrace(); 972 | } 973 | } 974 | 975 | /** 976 | * 18FF FOTA service. 977 | * 2AF6 Firmware data check characteristic. 978 | * READ | NOTIFY property of FOTA profile. 979 | */ 980 | public void executeReadFirmwareDataCheck() { 981 | try { 982 | mBflUploadBinder.executeReadCharacteristic( 983 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 984 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_DATA_CHECK.getCode() 985 | ); 986 | } catch (RemoteException e) { 987 | e.printStackTrace(); 988 | } 989 | } 990 | 991 | /** 992 | * 18FF FOTA service. 993 | * 2AF7 Firmware status characteristic. 994 | * READ | WRITE property function of FOTA profile. 995 | */ 996 | public void executeReadFirmwareStatus() { 997 | try { 998 | mBflUploadBinder.executeReadCharacteristic( 999 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1000 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_STATUS.getCode() 1001 | ); 1002 | } catch (RemoteException e) { 1003 | e.printStackTrace(); 1004 | } 1005 | } 1006 | 1007 | /** 1008 | * 180A Device information which is included service. 1009 | * 2A29 Manufacturer name characteristic. 1010 | * READ property function of FOTA profile. 1011 | */ 1012 | public void executeReadManufacturerName() { 1013 | try { 1014 | mBflUploadBinder.executeReadCharacteristic( 1015 | ServiceIdxCode.SERVICE_DEVICE_INFO.getCode(), 1016 | CharacteristicDeviceInfoIdxCode.CHARACTERISTIC_MANUFACTURER_NAME.getCode() 1017 | ); 1018 | }catch (RemoteException e) { 1019 | e.printStackTrace(); 1020 | } 1021 | } 1022 | 1023 | /** 1024 | * 180A Device information which is included service. 1025 | * 2A24 Model number characteristic. 1026 | * READ property function of FOTA profile. 1027 | */ 1028 | public void executeReadModelNumber() { 1029 | try { 1030 | mBflUploadBinder.executeReadCharacteristic( 1031 | ServiceIdxCode.SERVICE_DEVICE_INFO.getCode(), 1032 | CharacteristicDeviceInfoIdxCode.CHARACTERISTIC_MODEL_NUMBER.getCode() 1033 | ); 1034 | } catch (RemoteException e) { 1035 | e.printStackTrace(); 1036 | } 1037 | } 1038 | 1039 | /** 1040 | * 180A Device information which is included service. 1041 | * 2A25 Serial number characteristic. 1042 | * READ property function of FOTA profile. 1043 | */ 1044 | public void executeReadSerialNumber() { 1045 | try { 1046 | mBflUploadBinder.executeReadCharacteristic( 1047 | ServiceIdxCode.SERVICE_DEVICE_INFO.getCode(), 1048 | CharacteristicDeviceInfoIdxCode.CHARACTERISTIC_SERIAL_NUMBER.getCode() 1049 | ); 1050 | } catch (RemoteException e) { 1051 | e.printStackTrace(); 1052 | } 1053 | } 1054 | 1055 | /** 1056 | * 18FF FOTA service. 1057 | * 2AF1 Firmware new version characteristic. 1058 | * (READ |) WRITE property function of FOTA profile. 1059 | * 1060 | * @param firmwareVersion is new version information of firmware data which is going to be updated. 1061 | */ 1062 | public void executeWriteFirmwareNewVersion(String firmwareVersion) { 1063 | try { 1064 | mBflUploadBinder.executeWriteFirmwareNewVersion( 1065 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1066 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_NEW_VERSION.getCode(), 1067 | firmwareVersion 1068 | ); 1069 | } catch (RemoteException e) { 1070 | e.printStackTrace(); 1071 | } 1072 | } 1073 | 1074 | /** 1075 | * 18FF FOTA service. 1076 | * 2AF2 Firmware data characteristic. 1077 | * WRITE property function of FOTA profile. 1078 | * 1079 | * @param filePath is the location of the new firmware data in the smart device. 1080 | * @param sequenceNumber is the start location information of the firmware data which is going to be transmitted. 1081 | */ 1082 | public void executeFirmwareUpgrade(String filePath, int sequenceNumber) { 1083 | try { 1084 | mBflUploadBinder.executeWriteFirmwareData( 1085 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1086 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_DATA.getCode(), 1087 | filePath, 1088 | sequenceNumber 1089 | ); 1090 | } catch (RemoteException e) { 1091 | e.printStackTrace(); 1092 | } 1093 | } 1094 | 1095 | /** 1096 | * 18FF FOTA service. 1097 | * 2AF4 Checksum data characteristic. 1098 | * WRITE property function of FOTA profile. 1099 | * 1100 | * @param filePath is the location of the checksum data which is generated from firmware data. 1101 | */ 1102 | public void executeWriteChecksumData(String filePath) { 1103 | try { 1104 | mBflUploadBinder.executeWriteChecksumData( 1105 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1106 | CharacteristicFotaIdxCode.CHARACTERISTIC_CHECKSUM_DATA.getCode(), 1107 | filePath 1108 | ); 1109 | } catch (RemoteException e) { 1110 | e.printStackTrace(); 1111 | } 1112 | } 1113 | 1114 | /** 1115 | * 18FF FOTA service. 1116 | * 2AF6 Firmware upgrade type characteristic. 1117 | * WRITE property function of FOTA profile. 1118 | * 1119 | * @param typeFlag is normal or forced upgrade type. 1120 | */ 1121 | public void executeWriteFirmwareUpgradeType(byte typeFlag) { 1122 | try { 1123 | mBflUploadBinder.executeWriteFirmwareUpgradeType( 1124 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1125 | CharacteristicFotaIdxCode.CHARACTERISTIC_FIRMWARE_UPGRADE_TYPE.getCode(), 1126 | typeFlag 1127 | ); 1128 | } catch (RemoteException e) { 1129 | e.printStackTrace(); 1130 | } 1131 | } 1132 | 1133 | /** 1134 | * 18FF FOTA service. 1135 | * 2AF8 Reset characteristic. 1136 | * WRITE property function of FOTA profile. 1137 | * 1138 | * @param resetFlag is reset command flag. 1139 | */ 1140 | public void executeWriteReset(byte resetFlag) { 1141 | try { 1142 | mBflUploadBinder.executeWriteReset( 1143 | ServiceIdxCode.SERVICE_FIRMWARE_UPGRADE.getCode(), 1144 | CharacteristicFotaIdxCode.CHARACTERISTIC_RESET.getCode(), 1145 | resetFlag 1146 | ); 1147 | } catch (RemoteException e) { 1148 | e.printStackTrace(); 1149 | } 1150 | } 1151 | 1152 | /** 1153 | * Intent filter for BflFwUploadService. 1154 | * 1155 | * ACTION_GATT_CONNECTING: Bluetooth GATT connection creating state. 1156 | * ACTION_GATT_CONNECTED: Bluetooth GATT connection created state. 1157 | * ACTION_GATT_DISCONNECTING: Bluetooth GATT connection closing state. 1158 | * ACTION_GATT_DISCONNECTED: Bluetooth GATT connection closed state. 1159 | * ACTION_GATT_SERVICES_DISCOVERED: Bluetooth GATT service list discovered. 1160 | * ACTION_GATT_DATA_AVAILABLE: Bluetooth GATT service list get. 1161 | * 1162 | * Read properties of FOTA service. 1163 | * ACTION_FIRMWARE_CURRENT_VERSION_AVAILABLE: The target device current firmware version information. 1164 | * ACTION_FIRMWARE_NEW_VERSION_AVAILABLE: The target device new firmware version information to be going to be updated. 1165 | * ACTION_SEQUENCE_NUMBER_AVAILABLE: The sequence number is used to manage firmware data transmission. 1166 | * ACTION_FIRMWARE_DATA_CHECK_AVAILABLE: Firmware data integrity information. 1167 | * ACTION_FIRMWARE_STATUS_AVAILABLE: Firmware status information. 1168 | * 1169 | * Read properties of device information service. 1170 | * ACTION_MANUFACTURER_NAME_AVAILABLE: Manufacturer information. 1171 | * ACTION_MODEL_NUMBER_AVAILABLE: Model number information. 1172 | * ACTION_SERIAL_NUMBER_AVAILABLE: Serial number information. 1173 | * 1174 | * ACTION_DATA_AVAILABLE: Read data. 1175 | * 1176 | * Write properties of FOTA service. 1177 | * ACTION_FIRMWARE_NEW_VERSION_WRITABLE: Write new firmware version information. 1178 | * ACTION_FIRMWARE_DATA_WRITABLE: Firmware data transmission. 1179 | * ACTION_SEQUENCE_NUMBER_WRITABLE: The sequence number is used to manage firmware data transmission. 1180 | * ACTION_CHECKSUM_DATA_WRITABLE: Checksum data checks integrity of the firmware data. 1181 | * ACTION_FIRMWARE_UPGRADE_TYPE_WRITABLE: Apply firmware upgrade type. 1182 | * ACTION_RESET_WRITABLE: The target device reset. 1183 | * 1184 | * ACTION_DATA_WRITABLE: Write data. 1185 | * 1186 | * @return Intent filter. 1187 | */ 1188 | private static IntentFilter makeGattUpdateIntentFilter() { 1189 | final IntentFilter intentFilter = new IntentFilter(); 1190 | intentFilter.addAction(BflFwUploadService.ERROR_LOST_GATT); 1191 | intentFilter.addAction(BflFwUploadService.ERROR_LOST_DEVICE_INFORMATION); 1192 | 1193 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_CONNECTING); 1194 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_CONNECTED); 1195 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_DISCONNECTING); 1196 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_DISCONNECTED); 1197 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_SERVICES_DISCOVERED); 1198 | intentFilter.addAction(BflFwUploadService.ACTION_GATT_DATA_AVAILABLE); 1199 | // Read properties. 1200 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_CURRENT_VERSION_AVAILABLE); 1201 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_NEW_VERSION_AVAILABLE); 1202 | intentFilter.addAction(BflFwUploadService.ACTION_SEQUENCE_NUMBER_AVAILABLE); 1203 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_DATA_CHECK_AVAILABLE); 1204 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_STATUS_AVAILABLE); 1205 | intentFilter.addAction(BflFwUploadService.ACTION_MANUFACTURER_NAME_AVAILABLE); 1206 | intentFilter.addAction(BflFwUploadService.ACTION_MODEL_NUMBER_AVAILABLE); 1207 | intentFilter.addAction(BflFwUploadService.ACTION_SERIAL_NUMBER_AVAILABLE); 1208 | intentFilter.addAction(BflFwUploadService.ACTION_DATA_AVAILABLE); 1209 | // Write properties. 1210 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_NEW_VERSION_WRITABLE); 1211 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_DATA_WRITABLE); 1212 | intentFilter.addAction(BflFwUploadService.ACTION_SEQUENCE_NUMBER_WRITABLE); 1213 | intentFilter.addAction(BflFwUploadService.ACTION_CHECKSUM_DATA_WRITABLE); 1214 | intentFilter.addAction(BflFwUploadService.ACTION_FIRMWARE_UPGRADE_TYPE_WRITABLE); 1215 | intentFilter.addAction(BflFwUploadService.ACTION_RESET_WRITABLE); 1216 | intentFilter.addAction(BflFwUploadService.ACTION_DATA_WRITABLE); 1217 | return intentFilter; 1218 | } 1219 | } 1220 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflFwVerChecker.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.util.Log; 7 | 8 | import kr.co.sevencore.blefotalib.BflCodeList.FirmwareVersionStatusCode; 9 | import kr.co.sevencore.blefotalib.BflCodeList.UpgradeVersionTypeCode; 10 | 11 | /** 12 | * BflFwVerChecker.java 13 | * BLE FOTA Library Firmware Version Checker. 14 | * 15 | * 2015 SEVENCORE Co., Ltd. 16 | * 17 | * @author Jungwoo Park 18 | * @version 1.0.0 19 | * @since 2015-07-17 20 | * @see kr.co.sevencore.blefotalib.BflFwDownloader 21 | * @see kr.co.sevencore.blefotalib.BflFwUploader 22 | * @see kr.co.sevencore.blefotalib.BflCodeList 23 | */ 24 | public class BflFwVerChecker extends BroadcastReceiver { 25 | private final String BLE_FOTA_TAG = BflFwVerChecker.class.getSimpleName(); 26 | 27 | private static String sTargetVersion, sServerVersion; 28 | 29 | public final static String ACTION_TARGET_VERSION = "kr.co.sevencore.ble.fota.lib.util.ACTION_TARGET_VERSION"; 30 | public final static String ACTION_SERVER_VERSION = "kr.co.sevencore.ble.fota.lib.util.ACTION_SERVER_VERSION"; 31 | public final static String VERSION_INFO = "kr.co.sevencore.ble.fota.lib.util.VERSION_INFO"; 32 | 33 | 34 | /** 35 | * Compare firmware version information of the target device and the server updated asynchronously. 36 | * 37 | * @param context is used to check running state of the firmware download service. 38 | * @param intent identify each action of the broadcast. 39 | */ 40 | @Override 41 | public void onReceive(Context context, Intent intent) { 42 | final String action = intent.getAction(); 43 | Log.d(BLE_FOTA_TAG, "Firmware version checker received version information."); 44 | 45 | if (action != null) { 46 | if (ACTION_TARGET_VERSION.equals(action)) { 47 | sTargetVersion = intent.getStringExtra(VERSION_INFO); 48 | Log.d(BLE_FOTA_TAG, "Receive firmware version information of the target device."); 49 | 50 | } else if (ACTION_SERVER_VERSION.equals(action)) { 51 | sServerVersion = intent.getStringExtra(VERSION_INFO); 52 | Log.d(BLE_FOTA_TAG, "Receive firmware version information from the server."); 53 | } 54 | checkUpdate(context, sTargetVersion, sServerVersion); 55 | } 56 | } 57 | 58 | /** 59 | * Check firmware update is needed. 60 | * TODO: Version information control by ascending order and so on. 61 | * 62 | * @param targetVersion is firmware version information of the target device. 63 | * @param serverVersion is firmware version information from the server. 64 | */ 65 | private int checkUpdate(Context context, String targetVersion, String serverVersion) { 66 | if ((targetVersion != null) && (serverVersion != null)) { 67 | initVersionInfo(); 68 | 69 | if (BflUtil.compareVersion(targetVersion, serverVersion) == 70 | UpgradeVersionTypeCode.FIRMWARE_UP_TO_DATE.getCode()) { 71 | Log.i(BLE_FOTA_TAG, "Firmware version of the target device is up to date."); 72 | return FirmwareVersionStatusCode.FIRMWARE_VERSION_UP_TO_DATE.getCode(); 73 | 74 | } else { 75 | // Check firmware download service is running. 76 | if (BflUtil.isServiceRunning(context, BflFwDownloadService.class)) { 77 | try { 78 | // Unit test mode downloads firmware data all the ways. 79 | // TODO: If you wants to minimize networks use, add routine for checking the firmware data existence. 80 | Log.i(BLE_FOTA_TAG, "Firmware is going to be upgraded of downgraded."); 81 | BflFwDownloader.sBflDownloadBinder.getFirmwareUrl(); 82 | } catch (Exception e) { 83 | e.printStackTrace(); 84 | } 85 | } 86 | } 87 | } 88 | return FirmwareVersionStatusCode.FIRMWARE_VERSION_UP_TO_DATE.getCode(); 89 | } 90 | 91 | /** 92 | * Initialize version information values. 93 | */ 94 | private void initVersionInfo() { 95 | sTargetVersion = sServerVersion = null; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /blefotalib/src/main/java/kr/co/sevencore/blefotalib/BflUtil.java: -------------------------------------------------------------------------------- 1 | package kr.co.sevencore.blefotalib; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.util.Log; 6 | 7 | /** 8 | * BflUtil.java 9 | * BLE FOTA Library utility methods. 10 | * 11 | * 2015 SEVENCORE Co., Ltd. 12 | * 13 | * @author Jungwoo Park 14 | * @version 1.0.0 15 | * @since 2015-04-08 16 | */ 17 | public class BflUtil { 18 | private final static String BLE_FOTA_TAG = BflUtil.class.getSimpleName(); 19 | 20 | 21 | /** 22 | * Extract the firmware version information from the file name. 23 | * 24 | * @param fileName is the full name including extension. 25 | * @return file name without the extension. 26 | */ 27 | public static String extractVersionName(String fileName) { 28 | String[] versionNameArr = fileName.split("\\."); 29 | 30 | return versionNameArr[0]; 31 | } 32 | 33 | /** 34 | * Check the format of the firmware file name: 00-00-00 35 | * 36 | * @param fileVerName is the firmware version formed into file name. 37 | * @return true, if the firmware name conforms to the rules. 38 | */ 39 | public static boolean checkFileName(String fileVerName) { 40 | String[] nameElementArr = fileVerName.split("\\-"); 41 | int versionSize = 8; 42 | int verInfoElementCnt = 3; 43 | int verInfoElementSize = 2; 44 | int maxVerNum = 99; 45 | 46 | if((fileVerName.length() == versionSize) && (nameElementArr.length == verInfoElementCnt)) { 47 | for(int i = 0; i < verInfoElementCnt; i++) { 48 | for(int j = 0; j <= maxVerNum; j++) { 49 | String number = Integer.toString(j); 50 | 51 | if ((j < 10) && (nameElementArr[i].equals("0" + number)) && (i == verInfoElementSize)) { 52 | return true; 53 | } else if (nameElementArr[i].equals(number) && (i == verInfoElementSize)) { 54 | return true; 55 | } 56 | } 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | /** 63 | * Check the maximum file size of the firmware data. 64 | * 65 | * @param filePath is the pull path of the firmware data saved. 66 | * @return true, if the firmware file size is small than 100 KB. 67 | */ 68 | public static boolean checkFileSize(String filePath) { 69 | final int maxDataSize = 102400; // MAXIMUM FIRMWARE DATA SIZE: 100 KB 70 | int length = filePath.length(); 71 | 72 | if(length < maxDataSize) { 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | /** 79 | * Compare version information. 80 | * When version information format is AA-BB-CC, 81 | * AA: Major update 82 | * BB: Minor update 83 | * CC: Minor update 84 | * 85 | * @param firmwareVersion is current firmware version of the target device. 86 | * @param firmwareNewVersion is new firmware version from the server. 87 | * @return the information of update type. 88 | */ 89 | public static int compareVersion(String firmwareVersion, String firmwareNewVersion) { 90 | String[] currentVersionHierarchy = firmwareVersion.split("\\-"); 91 | String[] newVersionHierarchy = firmwareNewVersion.split("\\-"); 92 | 93 | if (!currentVersionHierarchy[0].equals(newVersionHierarchy[0])) { 94 | Log.d(BLE_FOTA_TAG, "current version hierarchy: " + currentVersionHierarchy[0] + ", new version: " + newVersionHierarchy[0]); 95 | if (Integer.parseInt(currentVersionHierarchy[0]) < Integer.parseInt(newVersionHierarchy[0])) { 96 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MAJOR_UPGRADE.getCode(); 97 | 98 | } else { 99 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MAJOR_DOWNGRADE.getCode(); 100 | } 101 | } else if (!currentVersionHierarchy[1].equals(newVersionHierarchy[1])) { 102 | if (Integer.parseInt(currentVersionHierarchy[1]) < Integer.parseInt(newVersionHierarchy[1])) { 103 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MINOR_UPGRADE.getCode(); 104 | 105 | } else { 106 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MINOR_DOWNGRADE.getCode(); 107 | } 108 | } else if (!currentVersionHierarchy[2].equals(newVersionHierarchy[2])) { 109 | if (Integer.parseInt(currentVersionHierarchy[2]) < Integer.parseInt(newVersionHierarchy[2])) { 110 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MINOR_UPGRADE.getCode(); 111 | 112 | } else { 113 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_MINOR_DOWNGRADE.getCode(); 114 | } 115 | } 116 | return BflCodeList.UpgradeVersionTypeCode.FIRMWARE_UP_TO_DATE.getCode(); 117 | } 118 | 119 | /** 120 | * Check service running status. 121 | * 122 | * @param context is gettable from caller application. 123 | * @param className is the name of service class. 124 | * @return If service is running, return true. 125 | */ 126 | public static boolean isServiceRunning(Context context, Class className) { 127 | ActivityManager activityManager = 128 | (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 129 | 130 | for(ActivityManager.RunningServiceInfo runningServiceInfo : 131 | activityManager.getRunningServices(Integer.MAX_VALUE)) { 132 | if(className.getName(). 133 | equals(runningServiceInfo.service.getClassName())) { 134 | Log.d(BLE_FOTA_TAG, "BLE FOTA service is running."); 135 | return true; 136 | } 137 | } 138 | Log.d(BLE_FOTA_TAG, "BLE FOTA service is NOT running."); 139 | return false; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable/field_of_business.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable/field_of_business.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sevencore/BLEFOTA/aa0d01caa63e83ef681cc4d56e7ddcd54128ca01/blefotalib/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /blefotalib/src/main/res/layout/bfl_listitem_device.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 17 | 18 | 22 | 23 | 27 | 28 | 35 | 36 | 43 | 44 | 45 | 49 | 50 | 57 | 58 | 65 | 66 | 67 | 68 | 73 | 74 | 83 | 84 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /blefotalib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BleFotaLib 3 | 4 | BLE is not supported 5 | Bluetooth is not supported. 6 | Bluetooth is disabled. 7 | 8 | Connected 9 | Disconnected 10 | 11 | NAME: 12 | MAC address: 13 | RSSI: 14 | Start FOTA 15 | 16 | Unknown device 17 | Unknown service 18 | Unknown characteristic 19 | 20 | -------------------------------------------------------------------------------- /blefotalib/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |