├── .gitignore ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── heyn │ │ └── erosplugin │ │ └── filemanger │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── heyn │ │ │ └── erosplugin │ │ │ └── filemanger │ │ │ └── MainActivity.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── heyn │ └── erosplugin │ └── filemanger │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── wx_filemanager ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── heyn │ └── erosplugin │ └── wx_filemanger │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── heyn │ │ └── erosplugin │ │ └── wx_filemanger │ │ ├── Application.java │ │ ├── activity │ │ ├── PermissionActionActivity.java │ │ ├── WxDownloadFileActivity.java │ │ └── WxUploadFileActivity.java │ │ ├── customInterface │ │ ├── IKeyBoardVisibleListener.java │ │ ├── OnProgressListener.java │ │ ├── onDownloadListener.java │ │ └── onUploadListener.java │ │ ├── event │ │ ├── AppIntentEvent.java │ │ ├── FileEvent.java │ │ ├── ParamsEvent.java │ │ ├── PxOrDpEvent.java │ │ └── StorageObject.java │ │ ├── module │ │ ├── CacheModule.java │ │ ├── FileModule.java │ │ └── UtilModule.java │ │ └── util │ │ ├── AndroidInfoUtil.java │ │ ├── Constant.java │ │ ├── DownloadFileUtil.java │ │ ├── ErosStorageUtil.java │ │ ├── ExMultipartBody.java │ │ ├── FileUtil.java │ │ ├── Md5Util.java │ │ ├── PermissionUtil.java │ │ ├── PixInfoUtil.java │ │ ├── SPUtil.java │ │ └── ToastUtil.java └── res │ ├── values │ ├── strings.xml │ └── styles.xml │ └── xml │ └── file_paths.xml └── test └── java └── com └── heyn └── erosplugin └── wx_filemanger └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/libraries 5 | /.idea/modules.xml 6 | /.idea/workspace.xml 7 | .DS_Store 8 | /build 9 | /captures 10 | .externalNativeBuild 11 | /.idea 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eros-plugin-filecache-manager 2 | 3 | #### 当前工具类支持--基础依赖包wxframework <= 1.0.9 的版本 4 | 5 | #### 如果您的基础依赖包wxframework的版本 > 1.0.9 , 为了使该工具类继续可以使用, 可前往: [Eros-plugin-android-extend](https://github.com/heynchy/eros-plugin-android-extend) 6 | 7 | #### 基于Eros框架下的相关功能(weex 与 Android 的交互): 8 | 1. Android端文件的查看,下载,预览基本功能 9 | 2. 本地缓存大小的获取,清除功能 10 | 3. 跳转至应用市场评分页(支持三星市场) 11 | 4. 获取软键盘的高度 12 | 5. 获取屏幕的高度(不包含虚拟按键),版本 0.0.9 13 | 6. 为下载添加token参数,版本 0.1 14 | 7. 修改打开Txt文档崩溃的BUG , 版本0.1.1 15 | 8. 修改下载文件的进度值的返回值问题, 版本0.1.2 16 | 9. 为了提高与JS端交互时下载后打开文件的灵活性,隐藏了下载完成后主动打开的功能,JS端可使用previewFile(params)主动打开, 版本0.1.3 17 | 10. 增加在当前app中打开其他app的方法; 18 | 增加Android端的本地存储工具类,等同于JS端的storage存储方式 19 | 本地存储和JS端的存储可通用, 即Android端可根据key值获取JS存储的数据; 20 | JS端可根据key值获取Android端存储的数据; 版本0.1.4 21 | 11. 增加本地选择文件并上传的功能(上传的代码逻辑类比Eros中的图片上传) 版本0.1.5 22 | 12. 增加打开xlsx文件的方式 版本0.1.6 23 | 13. 增加获取apk包的MD5值的方法, 用以完整性校验 版本0.1.9 24 | 14. 增加强制退出app的功能(kill进程) 版本0.2 25 | 15. 处理MD5值首位为0时自动消除0的BUG 版本0.2.1 26 | 16. 增加断点下载的功能downloadBreakPoint(), 版本0.2.4 27 | 17. 文件上传时添加打开指定文件夹的功能 版本0.2.5 28 | ## Usage 29 | ### Add dependency 30 | ```groovy 31 | dependencies { 32 | implementation 'com.github.heynchy:eros-plugin-filecache-manager:0.2.6' 33 | } 34 | 35 | ``` 36 | ### 添加混淆(如果需要断点下载功能) 37 | ```groovy 38 | # 断点下载的混淆 39 | -keepnames class com.liulishuo.okdownload.core.connection.DownloadOkHttp3Connection 40 | # ------- end com.liulishuo.okdownload:okhttp proguard rules ---- 41 | -keep class com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite { 42 | public com.liulishuo.okdownload.core.breakpoint.DownloadStore createRemitSelf(); 43 | public com.liulishuo.okdownload.core.breakpoint.BreakpointStoreOnSQLite(android.content.Context); 44 | } 45 | ``` 46 | 47 | ### 文件操作Module 48 | #### 1. Module名称: FileModule 49 | #### 2. 相关方法: 50 | 2.1 文件下载 51 | ```java 52 | 53 | /** 54 | * 下载文件的方法,带有进度的 55 | * 56 | * @param params 必须传递(Json 格式),相关参数包含url, fileId, fileName,token(需要权限的传递该参数) 57 | * @param success 下载成功的回调 58 | * @param failure 下载失败的回调 59 | * @param progress 下载进度的回调 60 | */ 61 | @JSMethod(uiThread = true) 62 | public void downloadFile(String params, final JSCallback success, final JSCallback failure, final JSCallback progress) 63 | ``` 64 | 2.1.1 文件断点下载(参数,返参跟downloadFile一样,就是方法名称不一样而已) 65 | ```java 66 | 67 | /** 68 | * 下载文件的方法,带有进度的 69 | * 70 | * @param params 必须传递(Json 格式),相关参数包含url, fileId, fileName,token(需要权限的传递该参数) 71 | * @param success 下载成功的回调 72 | * @param failure 下载失败的回调 73 | * @param progress 下载进度的回调 74 | */ 75 | @JSMethod(uiThread = true) 76 | public void downloadBreakPoint(String params, final JSCallback success, final JSCallback failure, final JSCallback progress) 77 | ``` 78 | 2.2 判断文件是否存在(是否已下载) 79 | ```java 80 | /** 81 | * 判断文件是否存在 82 | * 83 | * @param params Json格式,包含fileId 和 fileName 84 | * @param resultCallback 结果回调(true: 文件存在 false: 文件不存在) 85 | */ 86 | @JSMethod(uiThread = true) 87 | public void isFileExist(String params, JSCallback resultCallback) 88 | ``` 89 | 2.3 预览文件(查看文件) 90 | ```java 91 | /** 92 | * 预览文件 93 | * 94 | * @param params Json 格式,包含fileId 和fileName 95 | */ 96 | @JSMethod(uiThread = true) 97 | public void previewFile(String params) 98 | ``` 99 | 2.4 打开应用市场的评分页(应用详情页) 100 | ```java 101 | /** 102 | * 跳转至应用市场的评价界面 103 | */ 104 | @JSMethod(uiThread = true) 105 | public void marketComment() 106 | ``` 107 | 2.5 选择本地文件并上传(JS端的调用实现方式) 108 | ```java 109 | weex.requireModule('FileModule').pickAndUpload({ 110 | url: '', // 上传的接口地址 111 | header: { // 上传的相关头文件信息 112 | 'Content-Type':'multipart/form-data', // 必传参数 113 | 'Authorization':data // token (如果没有可以不传) 114 | }, 115 | params:{ 116 | // 其他参数的信息(可参考Eros图片上传时该处的取值格式进行设置) 117 | }, 118 | fileFolderPath:"test" // 路径以手机根目录为基础,传参只传根目录下的文件夹路径。 例:/storage/emulated/0/test, 只传test即可 119 | }, success =>{ 120 | // 上传成功的回调 121 | }, failure => { 122 | // 上传失败的回调 123 | },progress => { 124 | // 进度值的回调(0--100) 125 | }); 126 | ``` 127 | ### 缓存数据操作Module 128 | #### 1. Module 名称: CacheModule 129 | #### 2. 相关方法 130 | 2.1 获取缓存文件的大小 131 | ```java 132 | /** 133 | * 获取应用缓存的大小 134 | * 135 | * @param callback 结果回调(返回缓存大小的字符串, 例如"2.37MB") 136 | */ 137 | @JSMethod(uiThread = true) 138 | public void getCachesSize(JSCallback callback) 139 | ``` 140 | 2.2 清除缓存 141 | ```java 142 | /** 143 | * 清除应用缓存 144 | * 145 | * @param callback 结果回调(如果清除成功则返回true, 否则返回false) 146 | */ 147 | @JSMethod(uiThread = true) 148 | public void clearCaches(JSCallback callback) 149 | ``` 150 | ### Android相关功能的Module 151 | #### 1. Module 名称: UtilModule 152 | #### 2. 相关方法 153 | 2.1 获取Android手机软件盘的高度 154 | ```java 155 | /** 156 | * 获取Android手机软键盘的高度,返回值包括pxHeight(以px为单位)和dpHeight(以dp为单位)-----非监听形式 157 | * 158 | * @param callback 软键盘弹出的回调 159 | * @param callbackInvisible 软键盘隐藏的回调 160 | */ 161 | @JSMethod(uiThread = true) 162 | public void getSoftKeyInfo(final JSCallback callback, final JSCallback callbackInvisible) 163 | 164 | /** 165 | * 获取Android手机软键盘的高度----监听形式 166 | * 167 | * @param callback 软键盘弹出的回调 168 | * @param callbackInvisible 软键盘隐藏的回调 169 | */ 170 | @JSMethod(uiThread = true) 171 | public void getSoftKeyInfoAlive(final JSCallback callback, final JSCallback callbackInvisible) 172 | ``` 173 | 2.1.1 JS端使用说明 174 | ```java 175 | weex.requireModule('UtilModule').getSoftKeyInfo(visible => { 176 | // 软键盘弹出后的相关操作 177 | var date = JSON.parse(visible); 178 | console.log("heyn_OtherNormalModule1: "+ date.pxHeight); 179 | console.log("heyn_OtherNormalModule2: "+ date.dpHeight); 180 | }, invisible =>{ 181 | // 软键盘隐藏后的相关操作 182 | var date = JSON.parse(invisible); 183 | console.log("heyn_OtherNormalModule3: "+ date.pxHeight); 184 | console.log("heyn_OtherNormalModule4: "+ date.dpHeight); 185 | }); 186 | ``` 187 | 2.2 获取Android手机的屏幕高度(不包含虚拟按键) 188 | ```java 189 | /** 190 | * 获取Android屏幕尺寸,但是不包括虚拟键的高度 191 | * 192 | * @param callback 返回值的回调(已转换为JS端可用数据) 193 | */ 194 | @JSMethod(uiThread = true) 195 | public void getNoHasVirtualKey(final JSCallback callback) 196 | ``` 197 | 2.3 在当前app打开另外一个app 198 | ```java 199 | /** 200 | * 打开另外一个APP 201 | * 202 | * @param params 相关参数配置(JSON格式,包括如下参数) 203 | * ----- packageName: 包名(APPLICATION_ID)--->必须提供 204 | * ----- activityName: 页面的路径名(例如com.benmu.wx.activity.SplashActivity)--->可选 205 | * ----- key: 需要传参时的key--->可选(key 和 params,要么都为空,要么都不为空) 206 | * ----- params: Json格式,所传的参数--->可选(key 和 params,要么都为空,要么都不为空) 207 | * @param resultCallback 结果回调(true: 打开成功, false: 打开失败) 208 | * @param installed 安装回调(如果未安装,会响应---该回调) 209 | */ 210 | @JSMethod(uiThread = true) 211 | public void openOtherApp(String params, JSCallback resultCallback, JSCallback installed) 212 | ``` 213 | 2.3.1 JS端的使用方式----打开另一个APP 214 | ```java 215 | weex.requireModule('UtilModule').openOtherApp({ 216 | packageName:'com.test.heynchy', 217 | activityName:'com.benmu.wx.activity.SplashActivity', 218 | key:'TEST', 219 | params:'{"token":"mytoken","usename":"heynchy","useId":"helloID"}' 220 | }, result =>{ 221 | // 打开成功返回true, 打开失败返回false 222 | console.log("heyn","result: "+result) 223 | }, inststall =>{ 224 | // 如果检测到为未安装则执行该函数, 225 | // TODO 下载需要打开的app 226 | console.log("heyn","inststall: "+inststall) 227 | }); 228 | ``` 229 | 230 | 2.3.2 注意事项 231 | 1. activityName: 如果该值不为null, 即指定了打开的页面,则需要在AndroidManifest.xml 中的指定的页面activity 232 | 中添加 android:exported="true" ; 例如上面示例中,需要添加在 233 | { 242 | console.log("chy1234", "success===="+success); 243 | this.$notice.alert({ 244 | message:'success====='+success 245 | }); 246 | }, failure=>{ 247 | this.$notice.alert({ 248 | message:'failure====='+failure 249 | }); 250 | }); 251 | 2.5 强制退出APP 252 | weex.requireModule('UtilModule').exitAPP(); 253 | 254 | ### Android 原生方法工具类 255 | #### 存储工具类 ErosStorageUtil 256 | ##### 相关方法: 257 | 1. 本地数据保存 258 | ErosStorageUtil.put(Context context, String key, String value); 259 | 2. 存储数据移除 260 | ErosStorageUtil.remove(Context context, String key) 261 | 3. 存储数据获取 262 | ErosStorageUtil.get(Context context, String key),返回值String类型 263 | ### JS 调用方式----举例——清除缓存的使用 264 | ```java 265 | 270 | 271 | 286 | ``` 287 | #### 注意事项 288 | 1. 涉及到相关权限问题,需要手动添加至自己工程的AndroidManifest.xml中(针对上架的权限审核问题) 289 | 1.1 文件操作权限包括: 290 | 291 | 294 | 1.3 Android 8.0以上版本的APk安装时,需要安装权限: 295 | 296 | 297 | 298 | License 299 | ------- 300 | Copyright 2018-2020 heynchy 301 | 302 | Licensed under the Apache License, Version 2.0 (the "License"); 303 | you may not use this file except in compliance with the License. 304 | You may obtain a copy of the License at 305 | 306 | http://www.apache.org/licenses/LICENSE-2.0 307 | 308 | Unless required by applicable law or agreed to in writing, software 309 | distributed under the License is distributed on an "AS IS" BASIS, 310 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 311 | See the License for the specific language governing permissions and 312 | limitations under the License. 313 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.heyn.erosplugin.filemanger" 7 | minSdkVersion 19 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'com.android.support:appcompat-v7:28.0.0-rc02' 25 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 29 | implementation project(':wx_filemanager') 30 | } 31 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/heyn/erosplugin/filemanger/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.filemanger; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.heyn.erosplugin.filemanger", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/heyn/erosplugin/filemanger/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.filemanger; 2 | 3 | import android.content.Intent; 4 | import android.os.Environment; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | 9 | import com.heyn.erosplugin.wx_filemanger.activity.PermissionActionActivity; 10 | 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.math.BigInteger; 16 | import java.security.MessageDigest; 17 | import java.security.NoSuchAlgorithmException; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_main); 25 | // String apkPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/1.apk"; 26 | // Log.i("chy1234", "path===" + apkPath); 27 | String apkPath = this.getPackageCodePath(); // 获取Apk包存储路径 28 | try { 29 | MessageDigest dexDigest = MessageDigest.getInstance("MD5"); 30 | byte[] bytes = new byte[1024]; 31 | int byteCount; 32 | FileInputStream fis = new FileInputStream(new File(apkPath)); // 读取apk文件 33 | while ((byteCount = fis.read(bytes)) != -1) { 34 | dexDigest.update(bytes, 0, byteCount); 35 | } 36 | BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 计算apk文件的哈希值 37 | Log.i("chy1234", "sha1====" + bigInteger); 38 | String sha = bigInteger.toString(16); 39 | Log.i("chy1234", "sha=2===" + sha); 40 | Log.i("chy1234", "sha=3===" + sha.length()); 41 | Log.i("chy1234", "sha=4===" + getFileMD5(new File(apkPath))); 42 | fis.close(); 43 | // success.invoke(sha); 44 | } catch (NoSuchAlgorithmException e) { 45 | Log.i("chy1234", "sha=3===" + e); 46 | // failure.invoke(e.getMessage()); 47 | } catch (FileNotFoundException e) { 48 | Log.i("chy1234", "sha=3===" + e); 49 | // failure.invoke(e.getMessage()); 50 | } catch (IOException e) { 51 | Log.i("chy1234", "sha=3===" + e); 52 | } 53 | } 54 | 55 | public static String getFileMD5(File file) { 56 | if (!file.isFile()) { 57 | return null; 58 | } 59 | MessageDigest digest = null; 60 | FileInputStream in = null; 61 | byte buffer[] = new byte[1024]; 62 | int len; 63 | try { 64 | digest = MessageDigest.getInstance("MD5"); 65 | in = new FileInputStream(file); 66 | while ((len = in.read(buffer, 0, 1024)) != -1) { 67 | digest.update(buffer, 0, len); 68 | } 69 | in.close(); 70 | } catch (Exception e) { 71 | e.printStackTrace(); 72 | return null; 73 | } 74 | return bytesToHexString(digest.digest()); 75 | } 76 | 77 | public static String bytesToHexString(byte[] src) { 78 | StringBuilder stringBuilder = new StringBuilder(""); 79 | if (src == null || src.length <= 0) { 80 | return null; 81 | } 82 | for (int i = 0; i < src.length; i++) { 83 | int v = src[i] & 0xFF; 84 | String hv = Integer.toHexString(v); 85 | if (hv.length() < 2) { 86 | stringBuilder.append(0); 87 | } 88 | stringBuilder.append(hv); 89 | } 90 | return stringBuilder.toString(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FileManger 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/heyn/erosplugin/filemanger/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.filemanger; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.1.3' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://jitpack.io' } 23 | maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/heynchy/eros-plugin-filecache-manager/a8c500263f21e5f2282e6b264e6d21414f543ff9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Apr 21 13:59:22 CST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':wx_filemanager' 2 | -------------------------------------------------------------------------------- /wx_filemanager/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /wx_filemanager/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | 6 | 7 | 8 | defaultConfig { 9 | minSdkVersion 16 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true 16 | 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | } 27 | 28 | dependencies { 29 | implementation fileTree(dir: 'libs', include: ['*.jar']) 30 | 31 | implementation 'com.android.support:appcompat-v7:25.3.1' 32 | testImplementation 'junit:junit:4.12' 33 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 34 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 35 | compileOnly 'com.github.bmfe:WeexErosFramework:1.0.4' 36 | implementation 'com.google.code.gson:gson:2.8.5' 37 | // core 38 | implementation 'com.liulishuo.okdownload:okdownload:1.0.3' 39 | // provide sqlite to store breakpoints 40 | implementation 'com.liulishuo.okdownload:sqlite:1.0.3' 41 | } 42 | -------------------------------------------------------------------------------- /wx_filemanager/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /wx_filemanager/src/androidTest/java/com/heyn/erosplugin/wx_filemanger/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.heyn.erosplugin.wx_filemanger.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 16 | 19 | 20 | 25 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/Application.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger; 2 | 3 | import android.content.Context; 4 | 5 | import com.benmu.framework.BMWXApplication; 6 | 7 | /** 8 | * Created by Carry on 2017/8/23. 9 | */ 10 | 11 | public class Application extends BMWXApplication { 12 | private static volatile Application mInstance; 13 | 14 | @Override 15 | public void onCreate() { 16 | super.onCreate(); 17 | mInstance = this; 18 | } 19 | 20 | /** 21 | * 创建App的单例对象 22 | */ 23 | public synchronized static Application getInstance() { 24 | if (mInstance == null) { 25 | synchronized (Application.class) { 26 | if (null == mInstance) { 27 | mInstance = new Application(); 28 | } 29 | } 30 | } 31 | return mInstance; 32 | } 33 | 34 | public static Context getAppContext() { 35 | return getWXApplication(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/activity/PermissionActionActivity.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.ActivityInfo; 8 | import android.content.pm.PackageManager; 9 | import android.os.Bundle; 10 | import android.os.Environment; 11 | import android.support.annotation.NonNull; 12 | import android.support.annotation.Nullable; 13 | import android.text.TextUtils; 14 | import android.view.Gravity; 15 | import android.view.View; 16 | import android.view.Window; 17 | import android.view.WindowManager; 18 | 19 | import com.heyn.erosplugin.wx_filemanger.R; 20 | import com.heyn.erosplugin.wx_filemanger.util.FileUtil; 21 | import com.heyn.erosplugin.wx_filemanger.util.PermissionUtil; 22 | import com.heyn.erosplugin.wx_filemanger.util.ToastUtil; 23 | import com.taobao.weex.IWXRenderListener; 24 | import com.taobao.weex.WXSDKInstance; 25 | import com.taobao.weex.bridge.JSCallback; 26 | 27 | import java.io.File; 28 | 29 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_FIVE; 30 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_FOUR; 31 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_NUM; 32 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_ONE; 33 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_THREE; 34 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_TWO; 35 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.CUSTOM_CALLBACK; 36 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.DATA_PARAMAS; 37 | import static com.heyn.erosplugin.wx_filemanger.util.PermissionUtil.REQUEST_EXTERNAL_STORAGE; 38 | 39 | /** 40 | * Author: 崔海营 41 | * Date: 2018/9/19 42 | *

43 | * Introduce: 相关权限行为处理的Activity 44 | */ 45 | public class PermissionActionActivity extends Activity implements IWXRenderListener { 46 | private int mAction; // 操作行为 47 | private String mParamas; // 传递的参数 48 | private JSCallback mCallback; // 回调参数 49 | 50 | 51 | @Override 52 | protected void onCreate(@Nullable Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | init(); 55 | checkPermission(); 56 | } 57 | 58 | 59 | /** 60 | * 初始化基本配置 61 | */ 62 | private void init() { 63 | Window window = getWindow(); 64 | window.setGravity(Gravity.LEFT | Gravity.TOP); 65 | WindowManager.LayoutParams params = window.getAttributes(); 66 | params.x = 0; 67 | params.y = 0; 68 | params.height = 1; 69 | params.width = 1; 70 | params.alpha = 0.0f; 71 | window.setAttributes(params); 72 | mAction = getIntent().getIntExtra(ACTION_NUM, -1); 73 | mParamas = getIntent().getStringExtra(DATA_PARAMAS); 74 | mCallback = (JSCallback) getIntent().getSerializableExtra(CUSTOM_CALLBACK); 75 | } 76 | 77 | /** 78 | * 检查本地存储权限是否存在(不存在的就去申请) 79 | */ 80 | private void checkPermission() { 81 | if (PermissionUtil.hasStoragePermission(this)) { 82 | finish(); 83 | } else { 84 | PermissionUtil.getStoragePermissions(this); 85 | } 86 | } 87 | 88 | /** 89 | * 主动获取权限后的回调 90 | * 91 | * @param requestCode 92 | * @param permissions 93 | * @param grantResults 94 | */ 95 | @Override 96 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 97 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 98 | if (REQUEST_EXTERNAL_STORAGE == requestCode) { 99 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 100 | // 获取存储权限成功 101 | if (mAction == -1) { 102 | finish(); 103 | return; 104 | } 105 | switch (mAction) { 106 | case ACTION_ONE: // 文件是否存在的操作(有params(此处为绝对路径,已处理过) 和 callback) 107 | if (TextUtils.isEmpty(mParamas) || mCallback == null) { 108 | finish(); 109 | return; 110 | } 111 | if (FileUtil.isFileExist(mParamas)) { 112 | mCallback.invoke(true); 113 | } else { 114 | mCallback.invoke(false); 115 | } 116 | break; 117 | case ACTION_TWO: // 文件预览的操作 (仅有paramas(此处为绝对路径,已处理过)) 118 | if (new File(mParamas).exists()) { 119 | try { 120 | startActivity(FileUtil.openFile(mParamas)); 121 | } catch (ActivityNotFoundException e) { 122 | ToastUtil.getInstance().showToast(getResources() 123 | .getString(R.string.no_find_app)); 124 | } 125 | } else { 126 | ToastUtil.getInstance().showToast(getResources() 127 | .getString(R.string.file_not_exist)); 128 | } 129 | break; 130 | case ACTION_THREE: // 清除缓存的操作(仅有callback) 131 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 132 | FileUtil.deleteFiles(getExternalCacheDir()); 133 | FileUtil.deleteFiles(getCacheDir()); 134 | if (mCallback != null) { 135 | mCallback.invoke(1); 136 | } 137 | } else { 138 | if (mCallback != null) { 139 | mCallback.invoke(0); 140 | } 141 | } 142 | break; 143 | case ACTION_FOUR: // 获取缓存大小的操作(仅有callback) 144 | try { 145 | long size = FileUtil.getFolderSize(getExternalCacheDir()); 146 | size = size + FileUtil.getFolderSize(getCacheDir()); 147 | mCallback.invoke(FileUtil.getFormatSize(size)); 148 | } catch (Exception e) { 149 | mCallback.invoke(getResources().getString(R.string.default_size)); 150 | } 151 | break; 152 | case ACTION_FIVE: // 本地文件预览的操作 153 | if (new File(mParamas).exists()) { 154 | try { 155 | startActivity(FileUtil.openFile(mParamas)); 156 | } catch (ActivityNotFoundException e) { 157 | ToastUtil.getInstance().showToast(getResources() 158 | .getString(R.string.no_find_app)); 159 | } 160 | } else { 161 | ToastUtil.getInstance().showToast(getResources() 162 | .getString(R.string.file_not_exist)); 163 | } 164 | break; 165 | } 166 | } 167 | } 168 | finish(); 169 | } 170 | 171 | /** 172 | * 跳转至该页面的静态方法 173 | * 174 | * @param context 175 | */ 176 | public static void start(Context context, int action, String params, JSCallback callback) { 177 | Intent intent = new Intent(context, PermissionActionActivity.class); 178 | intent.putExtra(ACTION_NUM, action); 179 | intent.putExtra(DATA_PARAMAS, params); 180 | Bundle bundle = new Bundle(); 181 | bundle.putSerializable(CUSTOM_CALLBACK, callback); 182 | intent.putExtras(bundle); 183 | context.startActivity(intent); 184 | } 185 | 186 | @Override 187 | public void onViewCreated(WXSDKInstance instance, View view) { 188 | 189 | } 190 | 191 | @Override 192 | public void onRenderSuccess(WXSDKInstance instance, int width, int height) { 193 | 194 | } 195 | 196 | @Override 197 | public void onRefreshSuccess(WXSDKInstance instance, int width, int height) { 198 | 199 | } 200 | 201 | @Override 202 | public void onException(WXSDKInstance instance, String errCode, String msg) { 203 | 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/activity/WxDownloadFileActivity.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.ActivityInfo; 8 | import android.content.pm.PackageManager; 9 | import android.os.Bundle; 10 | import android.support.annotation.NonNull; 11 | import android.support.annotation.Nullable; 12 | import android.text.TextUtils; 13 | import android.util.Log; 14 | import android.view.Gravity; 15 | import android.view.View; 16 | import android.view.Window; 17 | import android.view.WindowManager; 18 | 19 | 20 | import com.google.gson.Gson; 21 | import com.heyn.erosplugin.wx_filemanger.R; 22 | import com.heyn.erosplugin.wx_filemanger.customInterface.onDownloadListener; 23 | import com.heyn.erosplugin.wx_filemanger.event.ParamsEvent; 24 | import com.heyn.erosplugin.wx_filemanger.util.DownloadFileUtil; 25 | import com.heyn.erosplugin.wx_filemanger.util.FileUtil; 26 | import com.heyn.erosplugin.wx_filemanger.util.PermissionUtil; 27 | import com.heyn.erosplugin.wx_filemanger.util.ToastUtil; 28 | import com.liulishuo.okdownload.DownloadTask; 29 | import com.liulishuo.okdownload.SpeedCalculator; 30 | import com.liulishuo.okdownload.StatusUtil; 31 | import com.liulishuo.okdownload.core.breakpoint.BlockInfo; 32 | import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo; 33 | import com.liulishuo.okdownload.core.cause.EndCause; 34 | import com.liulishuo.okdownload.core.listener.DownloadListener4WithSpeed; 35 | import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend; 36 | import com.taobao.weex.IWXRenderListener; 37 | import com.taobao.weex.WXSDKInstance; 38 | import com.taobao.weex.bridge.JSCallback; 39 | 40 | import java.io.File; 41 | import java.util.List; 42 | import java.util.Map; 43 | 44 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.DATA_PARAMAS; 45 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.FAILURE_CALLBACK; 46 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.PROGRESS_CALLBACK; 47 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.SUCCESS_CALLBACK; 48 | import static com.heyn.erosplugin.wx_filemanger.util.PermissionUtil.REQUEST_EXTERNAL_STORAGE; 49 | 50 | 51 | /** 52 | * Author: 崔海营 53 | * Date: 2018/9/19 54 | *

55 | * Introduce: 文件管理操作的活动窗口 56 | */ 57 | public class WxDownloadFileActivity extends Activity implements IWXRenderListener { 58 | private JSCallback mSuccessCB; 59 | private JSCallback mFailureCB; 60 | private JSCallback mProgressCB; 61 | private String mDataParams; 62 | private boolean mBreakPoint; 63 | 64 | @Override 65 | protected void onCreate(@Nullable Bundle savedInstanceState) { 66 | super.onCreate(savedInstanceState); 67 | init(); // 初始化配置 68 | checkPermission(); // 检查权限 69 | } 70 | 71 | 72 | /** 73 | * 初始化基本配置 74 | */ 75 | private void init() { 76 | Window window = getWindow(); 77 | window.setGravity(Gravity.LEFT | Gravity.TOP); 78 | WindowManager.LayoutParams params = window.getAttributes(); 79 | params.x = 0; 80 | params.y = 0; 81 | params.height = 1; 82 | params.width = 1; 83 | params.alpha = 0.0f; 84 | window.setAttributes(params); 85 | mSuccessCB = (JSCallback) getIntent().getSerializableExtra(SUCCESS_CALLBACK); 86 | mFailureCB = (JSCallback) getIntent().getSerializableExtra(FAILURE_CALLBACK); 87 | mProgressCB = (JSCallback) getIntent().getSerializableExtra(PROGRESS_CALLBACK); 88 | mDataParams = getIntent().getStringExtra(DATA_PARAMAS); 89 | mBreakPoint = getIntent().getBooleanExtra("Break_Point", true); 90 | } 91 | 92 | /** 93 | * 检查本地存储权限是否存在(不存在的就去申请) 94 | */ 95 | private void checkPermission() { 96 | if (PermissionUtil.hasStoragePermission(this)) { 97 | // 下载文件 98 | if (mBreakPoint){ 99 | downloadBreakPoint(); 100 | } else { 101 | downloadFile(); 102 | } 103 | } else { 104 | PermissionUtil.getStoragePermissions(this);// 主动申请权限 105 | } 106 | } 107 | 108 | /** 109 | * 下载文件 110 | */ 111 | private void downloadFile() { 112 | if (TextUtils.isEmpty(mDataParams)) { 113 | mFailureCB.invoke("下载参数错误"); 114 | finish(); 115 | return; 116 | } 117 | ParamsEvent paramsEvent = new Gson().fromJson(mDataParams, ParamsEvent.class); 118 | String fileId = paramsEvent.getFileId() == null ? "" : paramsEvent.getFileId(); 119 | String fileName = paramsEvent.getFileName(); 120 | String url = paramsEvent.getUrl(); 121 | String token = paramsEvent.getToken(); 122 | String saveDir = getExternalCacheDir() + "/" + fileId; 123 | DownloadFileUtil.getInstance().downloadFile(DownloadFileUtil.getRequest(token, url), 124 | saveDir, fileName, new onDownloadListener() { 125 | @Override 126 | public void onSuccess(String path) { 127 | if (mSuccessCB != null) { 128 | mSuccessCB.invoke("下载完成"); 129 | } 130 | // try { 131 | // startActivity(FileUtil.openFile(path)); 132 | // } catch (ActivityNotFoundException e) { 133 | // ToastUtil.getInstance().showToast(getResources() 134 | // .getString(R.string.no_find_app)); 135 | // } 136 | finish(); 137 | } 138 | 139 | @Override 140 | public void onFailure(String reason) { 141 | if (mFailureCB != null) { 142 | mFailureCB.invoke("下载失败:" + reason); 143 | } 144 | finish(); 145 | } 146 | 147 | @Override 148 | public void onProgress(int progress) { 149 | if (mProgressCB != null) { 150 | mProgressCB.invokeAndKeepAlive(progress); 151 | } 152 | } 153 | }); 154 | } 155 | 156 | /** 157 | * 根据权限的返回值进行相关处理 158 | * 159 | * @param requestCode 160 | * @param permissions 161 | * @param grantResults 162 | */ 163 | @Override 164 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 165 | @NonNull int[] grantResults) { 166 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 167 | if (REQUEST_EXTERNAL_STORAGE == requestCode) { 168 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 169 | // 获取存储权限成功 170 | if (mBreakPoint){ 171 | downloadBreakPoint(); 172 | } else { 173 | downloadFile(); 174 | } 175 | 176 | } 177 | } 178 | finish(); 179 | 180 | } 181 | 182 | 183 | /** 184 | * 跳转至该界面的静态方法 185 | * 186 | * @param context 187 | */ 188 | public static final void start(Context context, String dataParams, JSCallback success, JSCallback failure, 189 | JSCallback progress, boolean breakPoint) { 190 | Intent intent = new Intent(context, WxDownloadFileActivity.class); 191 | intent.putExtra(DATA_PARAMAS, dataParams); 192 | Bundle bundle = new Bundle(); 193 | if (success != null) { 194 | bundle.putSerializable(SUCCESS_CALLBACK, success); 195 | } 196 | if (failure != null) { 197 | bundle.putSerializable(FAILURE_CALLBACK, failure); 198 | } 199 | if (progress != null) { 200 | bundle.putSerializable(PROGRESS_CALLBACK, progress); 201 | } 202 | bundle.putBoolean("Break_Point",breakPoint); 203 | intent.putExtras(bundle); 204 | context.startActivity(intent); 205 | } 206 | 207 | @Override 208 | public void onViewCreated(WXSDKInstance instance, View view) { 209 | 210 | } 211 | 212 | @Override 213 | public void onRenderSuccess(WXSDKInstance instance, int width, int height) { 214 | 215 | } 216 | 217 | @Override 218 | public void onRefreshSuccess(WXSDKInstance instance, int width, int height) { 219 | 220 | } 221 | 222 | @Override 223 | public void onException(WXSDKInstance instance, String errCode, String msg) { 224 | 225 | } 226 | 227 | /** 228 | * 断点下载文件 229 | */ 230 | private void downloadBreakPoint() { 231 | if (TextUtils.isEmpty(mDataParams) && mFailureCB!= null ) { 232 | mFailureCB.invoke("下载参数错误"); 233 | finish(); 234 | return; 235 | } 236 | ParamsEvent paramsEvent = new Gson().fromJson(mDataParams, ParamsEvent.class); 237 | String fileId = paramsEvent.getFileId() == null ? "" : paramsEvent.getFileId(); 238 | String fileName = paramsEvent.getFileName(); 239 | String url = paramsEvent.getUrl(); 240 | String token = paramsEvent.getToken(); 241 | String saveDir = getExternalCacheDir() + "/" + fileId; 242 | DownloadTask.Builder builder = new DownloadTask.Builder(url, new File(saveDir)); 243 | if (!TextUtils.isEmpty(token)){ 244 | builder.addHeader("Authorization", token); 245 | } 246 | builder.setFilename(fileName) 247 | // the minimal interval millisecond for callback progress 248 | .setMinIntervalMillisCallbackProcess(30) 249 | // do re-download even if the task has already been completed in the past. 250 | .setPassIfAlreadyCompleted(false); 251 | builder.build().enqueue(new DownloadListener4WithSpeed() { 252 | @Override 253 | public void taskStart(@NonNull DownloadTask task) { 254 | 255 | } 256 | 257 | @Override 258 | public void connectStart(@NonNull DownloadTask task, int blockIndex, @NonNull Map> requestHeaderFields) { 259 | 260 | } 261 | 262 | @Override 263 | public void connectEnd(@NonNull DownloadTask task, int blockIndex, int responseCode, @NonNull Map> responseHeaderFields) { 264 | 265 | } 266 | 267 | @Override 268 | public void infoReady(@NonNull DownloadTask task, @NonNull BreakpointInfo info, boolean fromBreakpoint, @NonNull Listener4SpeedAssistExtend.Listener4SpeedModel model) { 269 | 270 | } 271 | 272 | @Override 273 | public void progressBlock(@NonNull DownloadTask task, int blockIndex, long currentBlockOffset, @NonNull SpeedCalculator blockSpeed) { 274 | 275 | } 276 | 277 | @Override 278 | public void progress(@NonNull DownloadTask task, long currentOffset, @NonNull SpeedCalculator taskSpeed) { 279 | double length = StatusUtil.getCurrentInfo(task).getTotalLength(); 280 | int percent = (int) (currentOffset/length *100); 281 | if (mProgressCB != null) { 282 | mProgressCB.invokeAndKeepAlive(percent); 283 | } 284 | } 285 | 286 | @Override 287 | public void blockEnd(@NonNull DownloadTask task, int blockIndex, BlockInfo info, @NonNull SpeedCalculator blockSpeed) { 288 | 289 | } 290 | 291 | @Override 292 | public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause, @NonNull SpeedCalculator taskSpeed) { 293 | if (StatusUtil.isCompleted(task) && mSuccessCB != null) { 294 | mSuccessCB.invoke("下载完成"); 295 | } else if (mFailureCB != null) { 296 | if (realCause != null) { 297 | mFailureCB.invoke("下载失败" + realCause.getMessage()); 298 | } else { 299 | mFailureCB.invoke("下载失败"); 300 | } 301 | } 302 | finish(); 303 | } 304 | }); 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/activity/WxUploadFileActivity.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.activity; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.PackageManager; 8 | import android.net.Uri; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.os.Environment; 12 | import android.support.annotation.NonNull; 13 | import android.support.annotation.Nullable; 14 | import android.text.TextUtils; 15 | import android.view.Gravity; 16 | import android.view.View; 17 | import android.view.Window; 18 | import android.view.WindowManager; 19 | 20 | import com.benmu.framework.manager.ManagerFactory; 21 | import com.benmu.framework.manager.impl.ParseManager; 22 | import com.google.gson.Gson; 23 | import com.heyn.erosplugin.wx_filemanger.customInterface.onUploadListener; 24 | import com.heyn.erosplugin.wx_filemanger.event.FileEvent; 25 | import com.heyn.erosplugin.wx_filemanger.util.DownloadFileUtil; 26 | import com.heyn.erosplugin.wx_filemanger.util.FileUtil; 27 | import com.heyn.erosplugin.wx_filemanger.util.PermissionUtil; 28 | import com.heyn.erosplugin.wx_filemanger.util.ToastUtil; 29 | import com.taobao.weex.IWXRenderListener; 30 | import com.taobao.weex.WXSDKInstance; 31 | import com.taobao.weex.bridge.JSCallback; 32 | 33 | import java.io.File; 34 | import java.util.HashMap; 35 | import java.util.Map; 36 | 37 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.DATA_PARAMAS; 38 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.FAILURE_CALLBACK; 39 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.PROGRESS_CALLBACK; 40 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.SUCCESS_CALLBACK; 41 | import static com.heyn.erosplugin.wx_filemanger.util.FileUtil.getAndroidUri; 42 | import static com.heyn.erosplugin.wx_filemanger.util.PermissionUtil.REQUEST_EXTERNAL_STORAGE; 43 | 44 | 45 | /** 46 | * Author: 崔海营 47 | * Date: 2018/9/19 48 | *

49 | * Introduce: 文件管理操作的活动窗口 50 | */ 51 | public class WxUploadFileActivity extends Activity implements IWXRenderListener { 52 | private JSCallback mSuccessCB; 53 | private JSCallback mFailureCB; 54 | private JSCallback mProgressCB; 55 | private String mDataParams; 56 | private FileEvent mEvent; 57 | 58 | @Override 59 | protected void onCreate(@Nullable Bundle savedInstanceState) { 60 | super.onCreate(savedInstanceState); 61 | init(); // 初始化配置 62 | checkPermission(); // 检查权限 63 | } 64 | 65 | 66 | /** 67 | * 初始化基本配置 68 | */ 69 | private void init() { 70 | Window window = getWindow(); 71 | window.setGravity(Gravity.LEFT | Gravity.TOP); 72 | WindowManager.LayoutParams params = window.getAttributes(); 73 | params.x = 0; 74 | params.y = 0; 75 | params.height = 1; 76 | params.width = 1; 77 | params.alpha = 0.0f; 78 | window.setAttributes(params); 79 | mSuccessCB = (JSCallback) getIntent().getSerializableExtra(SUCCESS_CALLBACK); 80 | mFailureCB = (JSCallback) getIntent().getSerializableExtra(FAILURE_CALLBACK); 81 | mProgressCB = (JSCallback) getIntent().getSerializableExtra(PROGRESS_CALLBACK); 82 | mDataParams = getIntent().getStringExtra(DATA_PARAMAS); 83 | mEvent = ManagerFactory.getManagerService(ParseManager.class).parseObject 84 | (mDataParams, FileEvent.class); 85 | } 86 | 87 | /** 88 | * 检查本地存储权限是否存在(不存在的就去申请) 89 | */ 90 | private void checkPermission() { 91 | if (PermissionUtil.hasStoragePermission(this)) { 92 | if (TextUtils.isEmpty(mEvent.getFileFolderPath())){ 93 | showFileChooser(mEvent.getType()); // 选择文件 94 | } else { 95 | String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + 96 | mEvent.getFileFolderPath() ; 97 | openAssignFolder(filePath); 98 | } 99 | 100 | } else { 101 | PermissionUtil.getStoragePermissions(this);// 主动申请权限 102 | } 103 | } 104 | 105 | /** 106 | * 上传资料时打开的文件选择器 107 | */ 108 | private void showFileChooser(String type) { 109 | if (TextUtils.isEmpty(type)) { 110 | type = "*/*"; 111 | } 112 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 113 | intent.setType(type); 114 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 115 | intent.addCategory(Intent.CATEGORY_OPENABLE); 116 | try { 117 | startActivityForResult(intent, 1111); 118 | } catch (ActivityNotFoundException ex) { 119 | ToastUtil.getInstance().showToast("没有找到文件管理器"); 120 | } 121 | } 122 | 123 | /** 124 | * 上传资料时打开的文件选择器 125 | */ 126 | private void openAssignFolder(String path) { 127 | String type = mEvent.getType(); 128 | if (TextUtils.isEmpty(type)) { 129 | type = "*/*"; 130 | } 131 | File file = new File(path); 132 | if(null==file || !file.exists()){ 133 | ToastUtil.getInstance().showToast("没有找到对应的文件夹, 请重试!"); 134 | finish(); 135 | return; 136 | } 137 | Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 138 | intent.addCategory(Intent.CATEGORY_DEFAULT); 139 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 140 | intent.setDataAndType(getAndroidUri(path), type); 141 | try { 142 | startActivityForResult(intent, 1111); 143 | } catch (ActivityNotFoundException ex) { 144 | ToastUtil.getInstance().showToast("没有找到文件管理器"); 145 | } 146 | } 147 | 148 | /** 149 | * 根据权限的返回值进行相关处理 150 | * 151 | * @param requestCode 152 | * @param permissions 153 | * @param grantResults 154 | */ 155 | @Override 156 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 157 | @NonNull int[] grantResults) { 158 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 159 | if (REQUEST_EXTERNAL_STORAGE == requestCode) { 160 | if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 161 | // 获取存储权限成功 162 | if (TextUtils.isEmpty(mEvent.getFileFolderPath())){ 163 | showFileChooser(mEvent.getType()); // 选择文件 164 | } else { 165 | String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + 166 | mEvent.getFileFolderPath() ; 167 | openAssignFolder(filePath); 168 | } 169 | } 170 | } 171 | finish(); 172 | 173 | } 174 | 175 | @Override 176 | protected void onActivityResult(int requestCode, final int resultCode, Intent data) { 177 | super.onActivityResult(requestCode, resultCode, data); 178 | switch (requestCode) { 179 | case 1111: 180 | // 获取选中文件的Uri地址 181 | if (resultCode == RESULT_OK) { 182 | Uri uri = data.getData(); 183 | if (uri == null) { 184 | if (mFailureCB != null) { 185 | mFailureCB.invoke("没有找到对应的文件"); 186 | } 187 | finish(); 188 | return; 189 | } 190 | String path = null; 191 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 192 | path = FileUtil.getPathByUrikitkat(this, uri); 193 | } else { 194 | path = FileUtil.getPathByUriOld(this, uri); 195 | } 196 | if (path == null) { 197 | path = ""; 198 | } 199 | // 根据相应的接口上传资源至服务器 200 | final File file = new File(path); 201 | if (!file.exists()) { 202 | if (mFailureCB != null) { 203 | mFailureCB.invoke("没有找到对应的文件"); 204 | } 205 | finish(); 206 | return; 207 | } 208 | // 文件上传 209 | if (mEvent == null || TextUtils.isEmpty(mEvent.getUrl())) { 210 | if (mFailureCB != null) { 211 | mFailureCB.invoke("请求链接异常!"); 212 | } 213 | finish(); 214 | return; 215 | } 216 | Map mapHeaders = new Gson().fromJson(mEvent.getHeader(), HashMap.class); 217 | Map paramMap = new Gson().fromJson(mEvent.getParams(), HashMap.class); 218 | DownloadFileUtil.getInstance().uploadFile(DownloadFileUtil.getRequest( 219 | mapHeaders, paramMap, mEvent.getUrl(), file, "", mProgressCB), 220 | new onUploadListener() { 221 | @Override 222 | public void onSuccess(String path) { 223 | if (mSuccessCB != null) { 224 | mSuccessCB.invoke(path); 225 | } 226 | finish(); 227 | } 228 | 229 | @Override 230 | public void onFailure(String reason) { 231 | if (mFailureCB != null) { 232 | mFailureCB.invoke(reason); 233 | } 234 | finish(); 235 | } 236 | }); 237 | } 238 | break; 239 | default: 240 | if (mFailureCB != null) { 241 | mFailureCB.invoke("没有找到该文件!"); 242 | } 243 | finish(); 244 | } 245 | } 246 | 247 | /** 248 | * 跳转至该界面的静态方法 249 | * 250 | * @param context 251 | */ 252 | public static final void start(Context context, String dataParams, JSCallback success, JSCallback failure, 253 | JSCallback progress) { 254 | Intent intent = new Intent(context, WxUploadFileActivity.class); 255 | intent.putExtra(DATA_PARAMAS, dataParams); 256 | Bundle bundle = new Bundle(); 257 | if (success != null) { 258 | bundle.putSerializable(SUCCESS_CALLBACK, success); 259 | } 260 | if (failure != null) { 261 | bundle.putSerializable(FAILURE_CALLBACK, failure); 262 | } 263 | if (progress != null) { 264 | bundle.putSerializable(PROGRESS_CALLBACK, progress); 265 | } 266 | intent.putExtras(bundle); 267 | context.startActivity(intent); 268 | } 269 | 270 | @Override 271 | public void onViewCreated(WXSDKInstance instance, View view) { 272 | 273 | } 274 | 275 | @Override 276 | public void onRenderSuccess(WXSDKInstance instance, int width, int height) { 277 | 278 | } 279 | 280 | @Override 281 | public void onRefreshSuccess(WXSDKInstance instance, int width, int height) { 282 | 283 | } 284 | 285 | @Override 286 | public void onException(WXSDKInstance instance, String errCode, String msg) { 287 | 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/customInterface/IKeyBoardVisibleListener.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.customInterface; 2 | 3 | /** 4 | * Author: 崔海营 5 | * Date: 2018/10/9 6 | *

7 | * Introduce: 8 | */ 9 | public interface IKeyBoardVisibleListener { 10 | void onSoftKeyBoardVisible(boolean visible, int softKeyHeight, int width); 11 | } 12 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/customInterface/OnProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.customInterface; 2 | 3 | /** 4 | * Author: 崔海营 5 | * Date: 2018/9/19 6 | *

7 | * Introduce: 8 | */ 9 | public interface OnProgressListener { 10 | /** 11 | * 上传的进度 12 | * 13 | * @param total 总的字节数 14 | * @param current 当前已上传的字节数 15 | */ 16 | void onProgress(long total, long current); 17 | } 18 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/customInterface/onDownloadListener.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.customInterface; 2 | 3 | /** 4 | * Author: 崔海营 5 | * Date: 2018/9/19 6 | *

7 | * Introduce: 8 | */ 9 | public interface onDownloadListener { 10 | 11 | /** 12 | * 下载成功 13 | * 14 | * @param path 返回下载的路径 15 | */ 16 | void onSuccess(String path); 17 | 18 | /** 19 | * 下载失败 20 | * 21 | * @param reason 返回下载失败的原因 22 | */ 23 | void onFailure(String reason); 24 | 25 | /** 26 | * 下载的进度 27 | * 28 | * @param progress 当前的进度值 29 | */ 30 | void onProgress(int progress); 31 | } 32 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/customInterface/onUploadListener.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.customInterface; 2 | 3 | /** 4 | * Author: 崔海营 5 | * Date: 2018/9/19 6 | *

7 | * Introduce: 8 | */ 9 | public interface onUploadListener { 10 | 11 | /** 12 | * 上传成功 13 | * 14 | * @param path 返回下载的路径 15 | */ 16 | void onSuccess(String path); 17 | 18 | /** 19 | * 上传失败 20 | * 21 | * @param reason 返回下载失败的原因 22 | */ 23 | void onFailure(String reason); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/event/AppIntentEvent.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Author: HeynChy 7 | * Date: 2018/11/21 8 | *

9 | * Introduce: 10 | */ 11 | public class AppIntentEvent implements Serializable { 12 | private String packageName; // 应用包名 13 | private String activityName; // 应用界面的路径名 14 | private String params; // 所传参数(Json格式) 15 | private String key; // 传参的KEY 16 | 17 | public String getPackageName() { 18 | return packageName; 19 | } 20 | 21 | public void setPackageName(String packageName) { 22 | this.packageName = packageName; 23 | } 24 | 25 | public String getActivityName() { 26 | return activityName; 27 | } 28 | 29 | public void setActivityName(String activityName) { 30 | this.activityName = activityName; 31 | } 32 | 33 | public String getParams() { 34 | return params; 35 | } 36 | 37 | public void setParams(String params) { 38 | this.params = params; 39 | } 40 | 41 | public String getKey() { 42 | return key; 43 | } 44 | 45 | public void setKey(String key) { 46 | this.key = key; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/event/FileEvent.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Author: Heynchy 7 | * Date: 2019/4/16 8 | *

9 | * Introduce: 10 | */ 11 | public class FileEvent implements Serializable { 12 | private String url; // 上传接口 13 | private String params; // 上传附带参数 json 14 | private String header; // 上传接口的头文件设置 15 | private String type; // 系统文件过滤类型 16 | private String fileFolderPath; // 指定打开目标文件夹的相对路径 17 | 18 | public String getUrl() { 19 | return url; 20 | } 21 | 22 | public void setUrl(String url) { 23 | this.url = url; 24 | } 25 | 26 | public String getParams() { 27 | return params; 28 | } 29 | 30 | public void setParams(String params) { 31 | this.params = params; 32 | } 33 | 34 | public String getHeader() { 35 | return header; 36 | } 37 | 38 | public void setHeader(String header) { 39 | this.header = header; 40 | } 41 | 42 | public String getType() { 43 | return type; 44 | } 45 | 46 | public void setType(String type) { 47 | this.type = type; 48 | } 49 | 50 | public String getFileFolderPath() { 51 | return fileFolderPath; 52 | } 53 | 54 | public void setFileFolderPath(String fileFolderPath) { 55 | this.fileFolderPath = fileFolderPath; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/event/ParamsEvent.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Author: Heynchy 7 | * Date: 2018/9/19 8 | *

9 | * Introduce: 下载文件的参数实体 10 | */ 11 | public class ParamsEvent implements Serializable { 12 | String url; // 下载链接 13 | String fileId; // 文件ID 14 | String fileName; // 文件名称 15 | String token; // 权限token 16 | String filePath; // 本地文件路径 17 | 18 | public String getUrl() { 19 | return url; 20 | } 21 | 22 | public void setUrl(String url) { 23 | this.url = url; 24 | } 25 | 26 | public String getFileId() { 27 | return fileId; 28 | } 29 | 30 | public void setFileId(String fileId) { 31 | this.fileId = fileId; 32 | } 33 | 34 | public String getFileName() { 35 | return fileName; 36 | } 37 | 38 | public void setFileName(String fileName) { 39 | this.fileName = fileName; 40 | } 41 | 42 | public String getToken() { 43 | return token; 44 | } 45 | 46 | public void setToken(String token) { 47 | this.token = token; 48 | } 49 | 50 | public String getFilePath() { 51 | return filePath; 52 | } 53 | 54 | public void setFilePath(String filePath) { 55 | this.filePath = filePath; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/event/PxOrDpEvent.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Author: Heynchy 7 | * Date: 2018/10/9 8 | *

9 | * Introduce: 10 | */ 11 | public class PxOrDpEvent implements Serializable { 12 | int pxHeight; 13 | int dpHeight; 14 | private String phoneModel; // 手机机型 15 | 16 | public int getDpHeight() { 17 | return dpHeight; 18 | } 19 | 20 | public void setDpHeight(int dpHeight) { 21 | this.dpHeight = dpHeight; 22 | } 23 | 24 | public int getPxHeight() { 25 | return pxHeight; 26 | } 27 | 28 | public void setPxHeight(int pxHeight) { 29 | this.pxHeight = pxHeight; 30 | } 31 | 32 | public String getPhoneModel() { 33 | return phoneModel; 34 | } 35 | 36 | public void setPhoneModel(String phoneModel) { 37 | this.phoneModel = phoneModel; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/event/StorageObject.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Author: Heynchy 7 | * Date: 2018/11/20 8 | *

9 | * Introduce: 10 | */ 11 | public class StorageObject implements Serializable { 12 | private String value; 13 | private long time; 14 | 15 | public long getTime() { 16 | return time; 17 | } 18 | 19 | public void setTime(long time) { 20 | this.time = time; 21 | } 22 | 23 | public String getValue() { 24 | return value; 25 | } 26 | 27 | public void setValue(String value) { 28 | this.value = value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/module/CacheModule.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.module; 2 | 3 | import android.app.Activity; 4 | import android.os.Environment; 5 | 6 | import com.alibaba.weex.plugin.annotation.WeexModule; 7 | import com.heyn.erosplugin.wx_filemanger.R; 8 | import com.heyn.erosplugin.wx_filemanger.activity.PermissionActionActivity; 9 | import com.heyn.erosplugin.wx_filemanger.util.FileUtil; 10 | import com.heyn.erosplugin.wx_filemanger.util.PermissionUtil; 11 | import com.taobao.weex.annotation.JSMethod; 12 | import com.taobao.weex.bridge.JSCallback; 13 | import com.taobao.weex.common.WXModule; 14 | 15 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_FOUR; 16 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_THREE; 17 | 18 | /** 19 | * Author: Heynchy 20 | * Date: 2018/9/19 21 | *

22 | * Introduce: 23 | */ 24 | @WeexModule(name = "CacheModule", lazyLoad = true) 25 | public class CacheModule extends WXModule { 26 | 27 | /** 28 | * 获取应用缓存的大小 29 | */ 30 | @JSMethod(uiThread = true) 31 | public void getCachesSize(JSCallback callback) { 32 | Activity activity = (Activity) mWXSDKInstance.getContext(); 33 | if (PermissionUtil.hasStoragePermission(activity)) { 34 | try { 35 | long size = FileUtil.getFolderSize(mWXSDKInstance.getContext().getExternalCacheDir()); 36 | size = size + FileUtil.getFolderSize(mWXSDKInstance.getContext().getCacheDir()); 37 | callback.invoke(FileUtil.getFormatSize(size)); 38 | } catch (Exception e) { 39 | callback.invoke(activity.getResources().getString(R.string.default_size)); 40 | } 41 | } else { 42 | PermissionActionActivity.start(mWXSDKInstance.getContext(), ACTION_FOUR, null, 43 | callback); 44 | } 45 | } 46 | 47 | /** 48 | * 清除应用缓存 49 | */ 50 | @JSMethod(uiThread = true) 51 | public void clearCaches(JSCallback callback) { 52 | Activity activity = (Activity) mWXSDKInstance.getContext(); 53 | if (PermissionUtil.hasStoragePermission(activity)) { 54 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { 55 | FileUtil.deleteFiles(mWXSDKInstance.getContext().getExternalCacheDir()); 56 | FileUtil.deleteFiles(mWXSDKInstance.getContext().getCacheDir()); 57 | if (callback != null) { 58 | callback.invoke(1); 59 | } 60 | } else { 61 | if (callback != null) { 62 | callback.invoke(0); 63 | } 64 | } 65 | } else { 66 | PermissionActionActivity.start(mWXSDKInstance.getContext(), ACTION_THREE, null, 67 | callback); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/module/FileModule.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.module; 2 | 3 | import android.app.Activity; 4 | import android.content.ActivityNotFoundException; 5 | import android.content.Intent; 6 | import android.net.Uri; 7 | import android.support.annotation.NonNull; 8 | import android.support.annotation.Nullable; 9 | import android.text.TextUtils; 10 | import android.util.Log; 11 | 12 | import com.alibaba.weex.plugin.annotation.WeexModule; 13 | import com.google.gson.Gson; 14 | import com.heyn.erosplugin.wx_filemanger.R; 15 | import com.heyn.erosplugin.wx_filemanger.activity.PermissionActionActivity; 16 | import com.heyn.erosplugin.wx_filemanger.activity.WxDownloadFileActivity; 17 | import com.heyn.erosplugin.wx_filemanger.activity.WxUploadFileActivity; 18 | import com.heyn.erosplugin.wx_filemanger.customInterface.onDownloadListener; 19 | import com.heyn.erosplugin.wx_filemanger.event.ParamsEvent; 20 | import com.heyn.erosplugin.wx_filemanger.util.DownloadFileUtil; 21 | import com.heyn.erosplugin.wx_filemanger.util.FileUtil; 22 | import com.heyn.erosplugin.wx_filemanger.util.PermissionUtil; 23 | import com.heyn.erosplugin.wx_filemanger.util.ToastUtil; 24 | import com.liulishuo.okdownload.DownloadTask; 25 | import com.liulishuo.okdownload.SpeedCalculator; 26 | import com.liulishuo.okdownload.StatusUtil; 27 | import com.liulishuo.okdownload.core.breakpoint.BlockInfo; 28 | import com.liulishuo.okdownload.core.breakpoint.BreakpointInfo; 29 | import com.liulishuo.okdownload.core.cause.EndCause; 30 | import com.liulishuo.okdownload.core.listener.DownloadListener4WithSpeed; 31 | import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend; 32 | import com.taobao.weex.annotation.JSMethod; 33 | import com.taobao.weex.bridge.JSCallback; 34 | import com.taobao.weex.common.WXModule; 35 | 36 | import java.io.File; 37 | import java.util.List; 38 | import java.util.Map; 39 | 40 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_FIVE; 41 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_ONE; 42 | import static com.heyn.erosplugin.wx_filemanger.util.Constant.ACTION_TWO; 43 | import static com.heyn.erosplugin.wx_filemanger.util.FileUtil.*; 44 | 45 | 46 | /** 47 | * Author: Heynchy 48 | * Date: 2018/9/19 49 | *

50 | * Introduce: 文件相关的操作,主要包括下载,预览功能 51 | */ 52 | @WeexModule(name = "FileModule", lazyLoad = true) 53 | public class FileModule extends WXModule { 54 | 55 | /** 56 | * 下载文件的方法,带有进度的 57 | * 58 | * @param params 相关参数包含url, fileId, fileName 59 | * @param success 下载成功的回调 60 | * @param failure 下载失败的回调 61 | * @param progress 下载进度的回调 62 | */ 63 | @JSMethod(uiThread = true) 64 | public void downloadFile(String params, final JSCallback success, final JSCallback failure, 65 | final JSCallback progress) { 66 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 67 | if (PermissionUtil.hasStoragePermission(activity)) { 68 | // 如果有存储权限就进行下载 69 | if (TextUtils.isEmpty(params)) { 70 | failure.invoke("下载参数丢失,请重试!"); 71 | return; 72 | } 73 | ParamsEvent paramsEvent = new Gson().fromJson(params, ParamsEvent.class); 74 | String fileId = paramsEvent.getFileId() == null ? "" : paramsEvent.getFileId(); 75 | String fileName = paramsEvent.getFileName(); 76 | String url = paramsEvent.getUrl(); 77 | String token = paramsEvent.getToken(); 78 | String saveDir = activity.getExternalCacheDir() + "/" + fileId; 79 | DownloadFileUtil.getInstance().downloadFile(DownloadFileUtil.getRequest(token, url), 80 | saveDir, fileName, new onDownloadListener() { 81 | @Override 82 | public void onSuccess(String path) { 83 | if (success != null) { 84 | success.invoke("下载完成"); 85 | } 86 | // try { 87 | // activity.startActivity(openFile(path)); 88 | // } catch (ActivityNotFoundException e) { 89 | // ToastUtil.getInstance().showToast(activity.getResources() 90 | // .getString(R.string.no_find_app)); 91 | // } 92 | } 93 | 94 | @Override 95 | public void onFailure(String reason) { 96 | if (failure != null) { 97 | failure.invoke("下载失败:" + reason); 98 | } 99 | } 100 | 101 | @Override 102 | public void onProgress(int pro) { 103 | if (progress != null) { 104 | progress.invokeAndKeepAlive(pro); 105 | } 106 | } 107 | }); 108 | 109 | } else { 110 | // 如果没有有存储权限就去申请 111 | WxDownloadFileActivity.start(mWXSDKInstance.getContext(), params, success, failure, 112 | progress, false); 113 | } 114 | } 115 | 116 | /** 117 | * 判断文件是否存在 118 | * 119 | * @param params 120 | * @param resultCallback 121 | */ 122 | @JSMethod(uiThread = true) 123 | public void isFileExist(String params, JSCallback resultCallback) { 124 | ParamsEvent event = new Gson().fromJson(params, ParamsEvent.class); 125 | if (TextUtils.isEmpty(event.getFileId()) || TextUtils.isEmpty(event.getFileName())) { 126 | resultCallback.invoke(false); 127 | return; 128 | } 129 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 130 | String filePath = mWXSDKInstance.getContext().getExternalCacheDir() + "/" + event.getFileId() 131 | + "/" + event.getFileName(); 132 | if (PermissionUtil.hasStoragePermission(activity)) { 133 | if (FileUtil.isFileExist(filePath)) { 134 | resultCallback.invoke(true); 135 | } else { 136 | resultCallback.invoke(false); 137 | } 138 | } else { 139 | PermissionActionActivity.start(mWXSDKInstance.getContext(), ACTION_ONE, filePath, 140 | resultCallback); 141 | } 142 | } 143 | 144 | /** 145 | * 预览文件 146 | * 147 | * @param params 148 | */ 149 | @JSMethod(uiThread = true) 150 | public void previewFile(String params) { 151 | ParamsEvent event = new Gson().fromJson(params, ParamsEvent.class); 152 | if (TextUtils.isEmpty(event.getFileId()) || TextUtils.isEmpty(event.getFileName())) { 153 | ToastUtil.getInstance().showToast("参数错误,文件打开失败!"); 154 | return; 155 | } 156 | String filePath = mWXSDKInstance.getContext().getExternalCacheDir() + "/" + 157 | event.getFileId() + "/" + event.getFileName(); 158 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 159 | if (PermissionUtil.hasStoragePermission(activity)) { 160 | if (new File(filePath).exists()) { 161 | try { 162 | activity.startActivity(openFile(filePath)); 163 | } catch (ActivityNotFoundException e) { 164 | ToastUtil.getInstance().showToast(activity.getResources() 165 | .getString(R.string.no_find_app)); 166 | } 167 | } else { 168 | ToastUtil.getInstance().showToast(activity.getResources() 169 | .getString(R.string.file_not_exist)); 170 | } 171 | } else { 172 | PermissionActionActivity.start(mWXSDKInstance.getContext(), ACTION_TWO, filePath, 173 | null); 174 | } 175 | } 176 | /** 177 | * 预览本地文件 178 | * 179 | * @param params 180 | */ 181 | @JSMethod(uiThread = true) 182 | public void previewLocalFile(String params) { 183 | ParamsEvent event = new Gson().fromJson(params, ParamsEvent.class); 184 | if (TextUtils.isEmpty(event.getFilePath())) { 185 | ToastUtil.getInstance().showToast("本地文件路径不存在!"); 186 | return; 187 | } 188 | String filePath = event.getFilePath(); 189 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 190 | if (PermissionUtil.hasStoragePermission(activity)) { 191 | if (new File(filePath).exists()) { 192 | try { 193 | activity.startActivity(openFile(filePath)); 194 | } catch (ActivityNotFoundException e) { 195 | ToastUtil.getInstance().showToast(activity.getResources() 196 | .getString(R.string.no_find_app)); 197 | } 198 | } else { 199 | ToastUtil.getInstance().showToast(activity.getResources() 200 | .getString(R.string.file_not_exist)); 201 | } 202 | } else { 203 | PermissionActionActivity.start(mWXSDKInstance.getContext(), ACTION_FIVE, filePath, 204 | null); 205 | } 206 | } 207 | /** 208 | * 跳转至应用市场的评价界面 209 | */ 210 | @JSMethod(uiThread = true) 211 | public void marketComment() { 212 | String appId = mWXSDKInstance.getContext().getPackageName(); 213 | try { 214 | if (android.os.Build.MANUFACTURER.equals("samsung")) { 215 | // 如果当前手机是三星手机 216 | Uri uri = Uri.parse("http://www.samsungapps.com/appquery/appDetail.as?appId=" + appId); 217 | Intent goToMarket = new Intent(); 218 | goToMarket.setClassName("com.sec.android.app.samsungapps", 219 | "com.sec.android.app.samsungapps.Main"); 220 | goToMarket.setData(uri); 221 | mWXSDKInstance.getContext().startActivity(goToMarket); 222 | } else { 223 | // 如果当前是其他类型的手机 224 | Uri uri = Uri.parse("market://details?id=" + appId); 225 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 226 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 227 | mWXSDKInstance.getContext().startActivity(intent); 228 | } 229 | } catch (Exception e) { 230 | ToastUtil.getInstance().showToast("您的手机没有安装Android应用市场"); 231 | e.printStackTrace(); 232 | } 233 | } 234 | 235 | /** 236 | * 上传本地文件 237 | * 238 | * @param params 相关参数 239 | * @param success 成功的回调 240 | * @param failure 失败的回调 241 | * @param progress 上传进度返回值 242 | */ 243 | @JSMethod(uiThread = true) 244 | public void pickAndUpload(String params, final JSCallback success, final JSCallback failure, 245 | final JSCallback progress) { 246 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 247 | WxUploadFileActivity.start(activity, params, success, failure, progress); 248 | } 249 | 250 | /** 251 | * 下载文件的方法,带有进度的 252 | * 253 | * @param params 相关参数包含url, fileId, fileName 254 | * @param success 下载成功的回调 255 | * @param failure 下载失败的回调 256 | * @param progress 下载进度的回调 257 | */ 258 | @JSMethod(uiThread = true) 259 | public void downloadBreakPoint(String params, final JSCallback success, final JSCallback failure, 260 | final JSCallback progress) { 261 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 262 | if (PermissionUtil.hasStoragePermission(activity)) { 263 | // 如果有存储权限就进行下载 264 | if (TextUtils.isEmpty(params)) { 265 | failure.invoke("下载参数丢失,请重试!"); 266 | return; 267 | } 268 | ParamsEvent paramsEvent = new Gson().fromJson(params, ParamsEvent.class); 269 | String fileId = paramsEvent.getFileId() == null ? "" : paramsEvent.getFileId(); 270 | String fileName = paramsEvent.getFileName(); 271 | String url = paramsEvent.getUrl(); 272 | String token = paramsEvent.getToken(); 273 | String saveDir = activity.getExternalCacheDir() + "/" + fileId; 274 | DownloadTask.Builder builder = new DownloadTask.Builder(url, new File(saveDir)); 275 | if (!TextUtils.isEmpty(token)){ 276 | builder.addHeader("Authorization", token); 277 | } 278 | builder.setFilename(fileName) 279 | // the minimal interval millisecond for callback progress 280 | .setMinIntervalMillisCallbackProcess(30) 281 | // do re-download even if the task has already been completed in the past. 282 | .setPassIfAlreadyCompleted(false); 283 | builder.build().enqueue(new DownloadListener4WithSpeed() { 284 | @Override 285 | public void taskStart(@NonNull DownloadTask task) { 286 | 287 | } 288 | 289 | @Override 290 | public void connectStart(@NonNull DownloadTask task, int blockIndex, @NonNull Map> requestHeaderFields) { 291 | 292 | } 293 | 294 | @Override 295 | public void connectEnd(@NonNull DownloadTask task, int blockIndex, int responseCode, @NonNull Map> responseHeaderFields) { 296 | 297 | } 298 | 299 | @Override 300 | public void infoReady(@NonNull DownloadTask task, @NonNull BreakpointInfo info, boolean fromBreakpoint, @NonNull Listener4SpeedAssistExtend.Listener4SpeedModel model) { 301 | 302 | } 303 | 304 | @Override 305 | public void progressBlock(@NonNull DownloadTask task, int blockIndex, long currentBlockOffset, @NonNull SpeedCalculator blockSpeed) { 306 | 307 | } 308 | 309 | @Override 310 | public void progress(@NonNull DownloadTask task, long currentOffset, @NonNull SpeedCalculator taskSpeed) { 311 | double length = StatusUtil.getCurrentInfo(task).getTotalLength(); 312 | Log.i("chy1234","progress==="+currentOffset/length *100); 313 | int percent = (int) (currentOffset/length *100); 314 | if (progress != null) { 315 | progress.invokeAndKeepAlive(percent); 316 | } 317 | } 318 | 319 | @Override 320 | public void blockEnd(@NonNull DownloadTask task, int blockIndex, BlockInfo info, @NonNull SpeedCalculator blockSpeed) { 321 | 322 | } 323 | 324 | @Override 325 | public void taskEnd(@NonNull DownloadTask task, @NonNull EndCause cause, @Nullable Exception realCause, @NonNull SpeedCalculator taskSpeed) { 326 | if (StatusUtil.isCompleted(task) || TextUtils.equals(cause.name(),"COMPLETED")){ 327 | success.invoke("下载完成"); 328 | } else { 329 | if (realCause != null){ 330 | failure.invoke("下载失败"+realCause.getMessage()); 331 | } else { 332 | failure.invoke("下载失败"); 333 | } 334 | } 335 | } 336 | }); 337 | } else { 338 | // 如果没有有存储权限就去申请 339 | WxDownloadFileActivity.start(mWXSDKInstance.getContext(), params, success, failure, 340 | progress, true); 341 | } 342 | } 343 | } 344 | 345 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/module/UtilModule.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.module; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Rect; 6 | import android.os.Process; 7 | import android.text.TextUtils; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.view.ViewTreeObserver; 11 | 12 | import com.alibaba.weex.plugin.annotation.WeexModule; 13 | import com.benmu.framework.utils.TextUtil; 14 | import com.google.gson.Gson; 15 | import com.heyn.erosplugin.wx_filemanger.customInterface.IKeyBoardVisibleListener; 16 | import com.heyn.erosplugin.wx_filemanger.event.AppIntentEvent; 17 | import com.heyn.erosplugin.wx_filemanger.event.PxOrDpEvent; 18 | import com.heyn.erosplugin.wx_filemanger.util.AndroidInfoUtil; 19 | import com.heyn.erosplugin.wx_filemanger.util.Md5Util; 20 | import com.heyn.erosplugin.wx_filemanger.util.PixInfoUtil; 21 | import com.taobao.weex.annotation.JSMethod; 22 | import com.taobao.weex.bridge.JSCallback; 23 | import com.taobao.weex.common.WXModule; 24 | 25 | import java.io.File; 26 | import java.io.FileInputStream; 27 | import java.io.FileNotFoundException; 28 | import java.io.IOException; 29 | import java.math.BigInteger; 30 | import java.security.MessageDigest; 31 | import java.security.NoSuchAlgorithmException; 32 | 33 | 34 | /** 35 | * Author: Heynchy 36 | * Date: 2018/10/9 37 | *

38 | * Introduce: Android 与 Eros交互所用到的日常工具类 39 | */ 40 | @WeexModule(name = "UtilModule", lazyLoad = true) 41 | public class UtilModule extends WXModule { 42 | boolean isVisiableForLast = false; 43 | 44 | /** 45 | * 获取Android手机软键盘的高度 46 | * 47 | * @param callback 软键盘弹出的回调 48 | * @param callbackInvisible 软键盘隐藏的回调 49 | */ 50 | @JSMethod(uiThread = true) 51 | public void getSoftKeyInfoAlive(final JSCallback callback, final JSCallback callbackInvisible) { 52 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 53 | addOnSoftKeyBoardVisibleListener(activity, new IKeyBoardVisibleListener() { 54 | @Override 55 | public void onSoftKeyBoardVisible(boolean visible, int windowBottom, int width) { 56 | if (width != 0) { 57 | windowBottom = (int) ((float) windowBottom / width * 750f); 58 | } 59 | String model = android.os.Build.MODEL; // 手机机型 60 | PxOrDpEvent event = new PxOrDpEvent(); 61 | event.setDpHeight(PixInfoUtil.px2dp(mWXSDKInstance.getContext(), windowBottom)); 62 | event.setPxHeight(windowBottom); 63 | if(!TextUtils.isEmpty(model)){ 64 | event.setPhoneModel(model); 65 | } 66 | if (visible && callback != null) { 67 | callback.invokeAndKeepAlive(new Gson().toJson(event)); 68 | } else if (!visible && callbackInvisible != null) { 69 | callbackInvisible.invokeAndKeepAlive(new Gson().toJson(event)); 70 | } 71 | } 72 | }); 73 | 74 | } 75 | 76 | /** 77 | * 获取Android手机软键盘的高度 78 | * 79 | * @param callback 软键盘弹出的回调 80 | * @param callbackInvisible 软键盘隐藏的回调 81 | */ 82 | @JSMethod(uiThread = true) 83 | public void getSoftKeyInfo(final JSCallback callback, final JSCallback callbackInvisible) { 84 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 85 | addOnSoftKeyBoardVisibleListener(activity, new IKeyBoardVisibleListener() { 86 | @Override 87 | public void onSoftKeyBoardVisible(boolean visible, int windowBottom, int width) { 88 | if (width != 0) { 89 | windowBottom = (int) ((float) windowBottom / width * 750f); 90 | } 91 | String model = android.os.Build.MODEL; // 手机机型 92 | PxOrDpEvent event = new PxOrDpEvent(); 93 | event.setDpHeight(PixInfoUtil.px2dp(mWXSDKInstance.getContext(), windowBottom)); 94 | event.setPxHeight(windowBottom); 95 | if(!TextUtils.isEmpty(model)){ 96 | event.setPhoneModel(model); 97 | } 98 | if (visible && callback != null) { 99 | callback.invoke(new Gson().toJson(event)); 100 | } else if (!visible && callbackInvisible != null) { 101 | callbackInvisible.invoke(new Gson().toJson(event)); 102 | } 103 | } 104 | }); 105 | 106 | } 107 | 108 | /** 109 | * 打开另外一个APP 110 | * 111 | * @param params 相关参数配置(JSON格式) 112 | * @param resultCallback 结果回调(true: 打开成功, false: 打开失败) 113 | * @param installed 安装回调(如果未安装,会响应---该回调) 114 | */ 115 | @JSMethod(uiThread = true) 116 | public void openOtherApp(String params, JSCallback resultCallback, JSCallback installed) { 117 | AppIntentEvent event = new Gson().fromJson(params, AppIntentEvent.class); 118 | Context context = mWXSDKInstance.getContext(); 119 | if (AndroidInfoUtil.checkApkExist(context, event.getPackageName())) { 120 | try { 121 | if (TextUtils.isEmpty(event.getActivityName())) { 122 | AndroidInfoUtil.openApk(context, event.getPackageName(), event.getKey(), 123 | event.getParams()); 124 | } else { 125 | AndroidInfoUtil.openApk(context, event.getPackageName(), event.getActivityName(), 126 | event.getKey(), event.getParams()); 127 | } 128 | resultCallback.invoke(true); 129 | } catch (Exception e) { 130 | resultCallback.invoke(false); 131 | } 132 | 133 | } else { 134 | // 应用包未安装 135 | installed.invoke(false); 136 | } 137 | } 138 | 139 | /** 140 | * 获取Android屏幕尺寸,但是不包括虚拟键的高度 141 | * 142 | * @param callback 返回值的回调(已转换为JS端可用数据) 143 | */ 144 | @JSMethod(uiThread = true) 145 | public void getNoHasVirtualKey(final JSCallback callback) { 146 | final Activity activity = (Activity) mWXSDKInstance.getContext(); 147 | // 获得屏幕整体的高度 148 | int hight = AndroidInfoUtil.getNoHasVirtualKey(activity); 149 | // 获得屏幕整体的宽度 150 | int width = AndroidInfoUtil.getScreenWidth(activity); 151 | if (width != 0) { 152 | hight = (int) ((float) hight / width * 750f); 153 | } 154 | if (callback != null) { 155 | callback.invoke(hight); 156 | } 157 | } 158 | 159 | public void addOnSoftKeyBoardVisibleListener(Activity activity, final IKeyBoardVisibleListener listener) { 160 | final View decorView = activity.getWindow().getDecorView(); 161 | decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 162 | @Override 163 | public void onGlobalLayout() { 164 | Rect rect = new Rect(); 165 | decorView.getWindowVisibleDisplayFrame(rect); 166 | // 获得屏幕整体的高度 167 | int hight = decorView.getHeight(); 168 | // 获得屏幕整体的宽度 169 | int width = decorView.getWidth(); 170 | // 获取虚拟按键的高度 171 | int virtualBar = AndroidInfoUtil.getVirtualBarHeigh(mWXSDKInstance.getContext()); 172 | //获得键盘高度 173 | int keyboardHeight = hight - rect.bottom - (virtualBar < 0 ? 0 : virtualBar); 174 | listener.onSoftKeyBoardVisible(keyboardHeight > 0, keyboardHeight, width); 175 | boolean visible = keyboardHeight > 0; 176 | if (visible != isVisiableForLast) { 177 | listener.onSoftKeyBoardVisible(visible, keyboardHeight, width); 178 | } 179 | isVisiableForLast = visible; 180 | } 181 | }); 182 | } 183 | 184 | /** 185 | * 获取Android APK 包的MD5值用于完整性校验 186 | * 187 | * @param success 188 | * @param failure 189 | */ 190 | @JSMethod(uiThread = true) 191 | public void getAPKMD5Code(final JSCallback success, final JSCallback failure) { 192 | String apkPath = mWXSDKInstance.getContext().getPackageCodePath(); // 获取Apk包存储路径 193 | try { 194 | MessageDigest dexDigest = MessageDigest.getInstance("MD5"); 195 | byte[] bytes = new byte[1024]; 196 | int byteCount; 197 | String sha = Md5Util.getFileMD5(new File(apkPath)); 198 | Log.i("HEYN_MD5","Current Md5 is " + sha); 199 | success.invoke(sha); 200 | // FileInputStream fis = new FileInputStream(new File(apkPath)); // 读取apk文件 201 | // while ((byteCount = fis.read(bytes)) != -1) { 202 | // dexDigest.update(bytes, 0, byteCount); 203 | // } 204 | // BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 计算apk文件的哈希值 205 | // String sha = bigInteger.toString(16); 206 | // fis.close(); 207 | // success.invoke(sha); 208 | } catch (NoSuchAlgorithmException e) { 209 | failure.invoke(e.getMessage()); 210 | } catch (Exception e) { 211 | failure.invoke(e.getMessage()); 212 | } 213 | } 214 | 215 | /** 216 | * 强制退出APP(KILL PROGRESS) 217 | */ 218 | @JSMethod(uiThread = true) 219 | public void exitAPP() { 220 | // 强制退出程序 221 | Process.killProcess(Process.myPid()); 222 | } 223 | 224 | 225 | } 226 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/AndroidInfoUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.pm.ApplicationInfo; 8 | import android.content.pm.PackageManager; 9 | import android.content.pm.ResolveInfo; 10 | import android.content.res.Resources; 11 | import android.text.TextUtils; 12 | import android.util.DisplayMetrics; 13 | import android.view.Display; 14 | import android.view.WindowManager; 15 | 16 | import java.lang.reflect.Method; 17 | import java.util.List; 18 | 19 | /** 20 | * Author: 崔海营 21 | * Date: 2018/10/10 22 | *

23 | * Introduce: Android手机 相关信息的工具类 24 | */ 25 | public class AndroidInfoUtil { 26 | 27 | 28 | /** 29 | * 获取包含虚拟键的整体屏幕高度 30 | * 31 | * @param activity 32 | * @return 33 | */ 34 | public static int getHasVirtualKey(Activity activity) { 35 | int pxHeight = 0; 36 | Display display = activity.getWindowManager().getDefaultDisplay(); 37 | DisplayMetrics dm = new DisplayMetrics(); 38 | @SuppressWarnings("rawtypes") 39 | Class c; 40 | try { 41 | c = Class.forName("android.view.Display"); 42 | @SuppressWarnings("unchecked") 43 | Method method = c.getMethod("getRealMetrics", DisplayMetrics.class); 44 | method.invoke(display, dm); 45 | pxHeight = dm.heightPixels; 46 | } catch (Exception e) { 47 | e.printStackTrace(); 48 | } 49 | return pxHeight; 50 | } 51 | 52 | /** 53 | * 获取屏幕尺寸,但是不包括虚拟键的高度 54 | * 55 | * @return 56 | */ 57 | public static int getNoHasVirtualKey(Activity activity) { 58 | int height = activity.getWindowManager().getDefaultDisplay().getHeight(); 59 | return height; 60 | } 61 | 62 | /** 63 | * 获取屏幕宽度,但是不包括虚拟键的高度 64 | * 65 | * @return 66 | */ 67 | public static int getScreenWidth(Activity activity) { 68 | int width = activity.getWindowManager().getDefaultDisplay().getWidth(); 69 | return width; 70 | } 71 | 72 | /** 73 | * 获取虚拟功能键高度 74 | * 75 | * @param context 76 | * @return 77 | */ 78 | public static int getVirtualBarHeigh(Context context) { 79 | int vh = 0; 80 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 81 | Display display = windowManager.getDefaultDisplay(); 82 | DisplayMetrics dm = new DisplayMetrics(); 83 | try { 84 | @SuppressWarnings("rawtypes") 85 | Class c = Class.forName("android.view.Display"); 86 | @SuppressWarnings("unchecked") 87 | Method method = c.getMethod("getRealMetrics", DisplayMetrics.class); 88 | method.invoke(display, dm); 89 | vh = dm.heightPixels - windowManager.getDefaultDisplay().getHeight(); 90 | } catch (Exception e) { 91 | e.printStackTrace(); 92 | } 93 | return vh; 94 | } 95 | 96 | /** 97 | * 根据包名打开 APK 98 | * 99 | * @param context 100 | * @param packageName 101 | * @param key 102 | * @param params 103 | */ 104 | public static void openApk(Context context, String packageName, String key, String params) { 105 | PackageManager packageManager = context.getPackageManager(); 106 | Intent intent = new Intent(); 107 | intent = packageManager.getLaunchIntentForPackage(packageName); 108 | if (!(TextUtils.isEmpty(key) || TextUtils.isEmpty(params))) { 109 | intent.putExtra(key, params); 110 | } 111 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 112 | context.startActivity(intent); 113 | } 114 | 115 | /** 116 | * 根据包名和类名打开APK 117 | * 118 | * @param context 119 | * @param packageName 120 | * @param activityName 121 | * @param key 122 | * @param params 123 | */ 124 | public static void openApk(Context context, String packageName, String activityName, String key, String params) { 125 | Intent intent = new Intent(Intent.ACTION_MAIN); 126 | ComponentName componentName = new ComponentName(packageName, activityName); 127 | intent.setComponent(componentName); 128 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 129 | if (!(TextUtils.isEmpty(key) || TextUtils.isEmpty(params))) { 130 | intent.putExtra(key, params); 131 | } 132 | context.startActivity(intent); 133 | } 134 | 135 | /** 136 | * 检测应用是否已安装 137 | * 138 | * @param context 139 | * @param packageName 140 | * @return 141 | */ 142 | public static boolean checkApkExist(Context context, String packageName) { 143 | if (TextUtils.isEmpty(packageName)) return false; 144 | try { 145 | ApplicationInfo info = context.getPackageManager().getApplicationInfo(packageName, 146 | PackageManager.GET_UNINSTALLED_PACKAGES); 147 | return true; 148 | } catch (PackageManager.NameNotFoundException e) { 149 | return false; 150 | } 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/Constant.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | /** 4 | * Author: 崔海营 5 | * Date: 2018/9/19 6 | *

7 | * Introduce: 相关的常量值 8 | */ 9 | public class Constant { 10 | public static final String SUCCESS_CALLBACK = "success_callback";// 下载文件成功的回调参数 11 | public static final String FAILURE_CALLBACK = "failure_callback";// 下载文件失败的回调参数 12 | public static final String PROGRESS_CALLBACK = "progress_callback";// 下载文件进度的回调参数 13 | public static final String DATA_PARAMAS = "data_params"; // 交互参数 14 | 15 | public static final String ACTION_NUM = "action_num"; // 操作的参数 16 | public static final int ACTION_ONE = 1; // 判断文件是否存在 17 | public static final int ACTION_TWO = 2; // 预览文件操作 18 | public static final int ACTION_THREE = 3; // 清除缓存操作 19 | public static final int ACTION_FOUR = 4; // 获取缓存大小的操作 20 | public static final int ACTION_FIVE = 5; // 预览本地文件操作 21 | public static final String CUSTOM_CALLBACK = "custom_callback"; // 普通的回调参数 22 | } 23 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/DownloadFileUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | 4 | import android.text.TextUtils; 5 | 6 | import com.heyn.erosplugin.wx_filemanger.customInterface.OnProgressListener; 7 | import com.heyn.erosplugin.wx_filemanger.customInterface.onDownloadListener; 8 | import com.heyn.erosplugin.wx_filemanger.customInterface.onUploadListener; 9 | import com.taobao.weex.bridge.JSCallback; 10 | 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.util.Map; 16 | 17 | import okhttp3.Call; 18 | import okhttp3.Callback; 19 | import okhttp3.Headers; 20 | import okhttp3.MultipartBody; 21 | import okhttp3.OkHttpClient; 22 | import okhttp3.Request; 23 | import okhttp3.RequestBody; 24 | import okhttp3.Response; 25 | 26 | /** 27 | * Created by yufs on 2017/8/16. 28 | */ 29 | 30 | public class DownloadFileUtil { 31 | public static final int DOWNLOAD_FAIL = 0; 32 | public static final int DOWNLOAD_PROGRESS = 1; 33 | public static final int DOWNLOAD_SUCCESS = 2; 34 | private static volatile DownloadFileUtil downloadInstance; 35 | private final OkHttpClient okHttpClient; 36 | 37 | /** 38 | * DownloadFileUtil 的单例 39 | * 40 | * @return 41 | */ 42 | public static DownloadFileUtil getInstance() { 43 | if (downloadInstance == null) { 44 | synchronized (DownloadFileUtil.class) { 45 | if (downloadInstance == null) { 46 | downloadInstance = new DownloadFileUtil(); 47 | } 48 | } 49 | } 50 | return downloadInstance; 51 | } 52 | 53 | private DownloadFileUtil() { 54 | okHttpClient = new OkHttpClient(); 55 | } 56 | 57 | /** 58 | * 带有进度返回的下载 59 | * 60 | * @param request 请求的配置request 61 | * @param saveDir 本地保存文件的绝对路径 62 | * @param fileName 文件名称 63 | * @param listener 下载过程监听器 64 | */ 65 | public void downloadFile(final Request request, final String saveDir, final String fileName, final onDownloadListener listener) { 66 | // Request request = new Request.Builder().url(url).build(); 67 | okHttpClient.newCall(request).enqueue(new Callback() { 68 | @Override 69 | public void onFailure(Call call, IOException e) { 70 | if (listener != null) { 71 | listener.onFailure(e.toString()); 72 | } 73 | } 74 | 75 | @Override 76 | public void onResponse(Call call, Response response) throws IOException { 77 | if (response.isSuccessful()) { 78 | InputStream is = null; 79 | byte[] buf = new byte[500]; 80 | int len = 0; 81 | FileOutputStream fos = null; 82 | try { 83 | is = response.body().byteStream(); 84 | long total = response.body().contentLength(); 85 | String savePath = isExistDir(saveDir); 86 | File file = new File(savePath, fileName); 87 | fos = new FileOutputStream(file); 88 | long sum = 0; 89 | while ((len = is.read(buf)) != -1) { 90 | fos.write(buf, 0, len); 91 | sum += len; 92 | int progress = (int) (sum * 1.0f / total * 100); 93 | //下载中 94 | if (listener != null) { 95 | listener.onProgress(progress); 96 | } 97 | } 98 | fos.flush(); 99 | //下载完成 100 | if (listener != null) { 101 | listener.onSuccess(file.getAbsolutePath()); 102 | } 103 | } catch (Exception e) { 104 | if (listener != null) { 105 | listener.onFailure(e.toString()); 106 | } 107 | } finally { 108 | try { 109 | if (is != null) 110 | is.close(); 111 | if (fos != null) { 112 | fos.close(); 113 | } 114 | } catch (IOException e) { 115 | 116 | } 117 | } 118 | } else { 119 | if (listener != null) { 120 | listener.onFailure("url请求异常,无法建立链接"); 121 | } 122 | } 123 | } 124 | }); 125 | } 126 | 127 | /** 128 | * 下载不带进度 129 | * 130 | * @param url 请求的url 131 | * @param saveDir 文件的保存路径 132 | * @param fileName 文件名 133 | * @param listener 下载监听器 134 | */ 135 | public void downloadNoProgress(final String url, final String saveDir, final String fileName, 136 | final onDownloadListener listener) { 137 | Request request = new Request.Builder().url(url).build(); 138 | okHttpClient.newCall(request).enqueue(new Callback() { 139 | @Override 140 | public void onFailure(Call call, IOException e) { 141 | if (listener != null) { 142 | listener.onFailure(e.toString()); 143 | } 144 | } 145 | 146 | @Override 147 | public void onResponse(Call call, Response response) throws IOException { 148 | if (response.isSuccessful()) { 149 | InputStream is = response.body().byteStream(); 150 | String filePath = FileUtil.saveToSDCard(saveDir, fileName, is); 151 | if (listener != null) { 152 | listener.onSuccess(filePath); 153 | } 154 | } else { 155 | if (listener != null) { 156 | listener.onFailure("url请求异常,无法建立链接!"); 157 | } 158 | } 159 | } 160 | }); 161 | } 162 | 163 | /** 164 | * 文件上传 165 | * 166 | * @param request 167 | * @param listener 168 | */ 169 | public void uploadFile(final Request request, final onUploadListener listener) { 170 | okHttpClient.newCall(request).enqueue(new Callback() { 171 | @Override 172 | public void onFailure(Call call, IOException e) { 173 | if (listener != null) { 174 | listener.onFailure(e.toString()); 175 | } 176 | } 177 | 178 | @Override 179 | public void onResponse(Call call, Response response) throws IOException { 180 | try { 181 | if (response.isSuccessful()) { 182 | //下载完成 183 | if (listener != null) { 184 | listener.onSuccess(response.body().string()); 185 | } 186 | } else { 187 | if (listener != null) { 188 | listener.onFailure("文件上传失败"); 189 | } 190 | } 191 | } catch (Exception e) { 192 | if (listener != null) { 193 | listener.onFailure("文件上传失败: " + e.getMessage()); 194 | } 195 | } finally { 196 | if (response.body() != null) { 197 | response.close(); 198 | } 199 | } 200 | } 201 | }); 202 | } 203 | 204 | /** 205 | * 判断内存中是否存在该文件,如果不存在则新建该文件 206 | * 207 | * @param saveDir 208 | * @return 209 | * @throws IOException 210 | */ 211 | private String isExistDir(String saveDir) throws IOException { 212 | File downloadFile = new File(saveDir); 213 | if (!downloadFile.mkdirs()) { 214 | downloadFile.createNewFile(); 215 | } 216 | String savePath = downloadFile.getAbsolutePath(); 217 | return savePath; 218 | } 219 | 220 | /** 221 | * 根据是否存在token返回合适的Request 222 | * 223 | * @param token 224 | * @return 225 | */ 226 | public static Request getRequest(String token, String url) { 227 | Request request; 228 | if (TextUtils.isEmpty(token)) { 229 | request = new Request.Builder().url(url).build(); 230 | } else { 231 | request = new Request.Builder().url(url) 232 | .addHeader("Authorization", token) 233 | .build(); 234 | } 235 | return request; 236 | } 237 | 238 | /** 239 | * 文件上传创建合适的Request 240 | * 241 | * @param headers 头文件的相关参数值(Map 类型) 242 | * @param params 其他表单参数 243 | * @param url 上传的接口路径 244 | * @return request 245 | */ 246 | public static Request getRequest(Map headers, Map params, String url, File file, String fileKey, final JSCallback progress) { 247 | Request.Builder requestBuilder = new Request.Builder().url(url); 248 | // 添加头文件的相关参数(token和其他) 249 | if (headers != null && !headers.isEmpty()) { 250 | Headers.Builder headerBuilder = new Headers.Builder(); 251 | for (String key : headers.keySet()) { 252 | headerBuilder.add(key, headers.get(key)); 253 | } 254 | requestBuilder.headers(headerBuilder.build()); 255 | } 256 | MultipartBody.Builder bodyBulid = new MultipartBody.Builder(); 257 | // 设置类型 258 | bodyBulid.setType(MultipartBody.FORM); 259 | // 追加参数 260 | if (params != null && !params.isEmpty()) { 261 | for (String key : params.keySet()) { 262 | Object object = params.get(key); 263 | if (!(object instanceof File)) { 264 | bodyBulid.addFormDataPart(key, object.toString()); 265 | } 266 | } 267 | } 268 | if (TextUtils.isEmpty(fileKey)) { 269 | fileKey = "file"; 270 | } 271 | bodyBulid.addFormDataPart(fileKey, file.getName(), RequestBody.create(null, file)); 272 | // 创建ExMultipartBody代理类,使其能够返回进度值 273 | ExMultipartBody exMultipartBody = new ExMultipartBody(bodyBulid.build(), 274 | new OnProgressListener() { 275 | @Override 276 | public void onProgress(long total, long current) { 277 | if (progress != null && total != 0) { 278 | progress.invokeAndKeepAlive((int) current*100 / total); 279 | } 280 | } 281 | }); 282 | requestBuilder.post(exMultipartBody); 283 | return requestBuilder.build(); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/ErosStorageUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.content.Context; 4 | import android.text.TextUtils; 5 | 6 | import com.benmu.framework.manager.ManagerFactory; 7 | import com.benmu.framework.manager.StorageManager; 8 | import com.google.gson.Gson; 9 | import com.heyn.erosplugin.wx_filemanger.event.StorageObject; 10 | 11 | /** 12 | * Author: Heynchy 13 | * Date: 2018/11/21 14 | *

15 | * Introduce: 16 | */ 17 | public class ErosStorageUtil { 18 | /** 19 | * 基于Eros框架下的数据存储 20 | * 21 | * @param context 22 | * @param key 23 | * @param value 24 | */ 25 | public static void put(Context context, String key, String value) { 26 | if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) { 27 | return; 28 | } 29 | StorageManager storageManager = ManagerFactory.getManagerService(StorageManager.class); 30 | StorageObject object = new StorageObject(); 31 | object.setTime(System.currentTimeMillis()); 32 | object.setValue(value); 33 | if (storageManager != null) { 34 | storageManager.setData(context, key, new Gson().toJson(object)); 35 | } 36 | } 37 | 38 | /** 39 | * 基于Eros框架下的数据移除 40 | * 41 | * @param context 42 | * @param key key值 43 | */ 44 | public static void remove(Context context, String key) { 45 | if (TextUtils.isEmpty(key)) { 46 | return; 47 | } 48 | StorageManager storageManager = ManagerFactory.getManagerService(StorageManager.class); 49 | if (storageManager != null) { 50 | storageManager.deleteData(context, key); 51 | } 52 | } 53 | 54 | /** 55 | * 基于Eros框架下的数据移除 56 | * 57 | * @param context 58 | * @param key key值 59 | */ 60 | public static String get(Context context, String key) { 61 | if (TextUtils.isEmpty(key)) { 62 | return null; 63 | } 64 | StorageManager storageManager = ManagerFactory.getManagerService(StorageManager.class); 65 | if (storageManager != null) { 66 | String result = storageManager.getData(context, key); 67 | if (!TextUtils.isEmpty(result)) { 68 | StorageObject object = new Gson().fromJson(result, StorageObject.class); 69 | result = object.getValue(); 70 | } 71 | return result; 72 | } 73 | return null; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/ExMultipartBody.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | 4 | import com.heyn.erosplugin.wx_filemanger.customInterface.OnProgressListener; 5 | 6 | import java.io.IOException; 7 | 8 | import okhttp3.MediaType; 9 | import okhttp3.MultipartBody; 10 | import okhttp3.RequestBody; 11 | import okio.Buffer; 12 | import okio.BufferedSink; 13 | import okio.ForwardingSink; 14 | import okio.Okio; 15 | 16 | /** 17 | * Author: Heynchy 18 | * Date: 2019/4/16 19 | *

20 | * Introduce: 21 | */ 22 | public class ExMultipartBody extends RequestBody { 23 | 24 | private MultipartBody mMultipartBody; 25 | private OnProgressListener mProgressListener; 26 | private long mCurrentLength; 27 | 28 | public ExMultipartBody(MultipartBody multipartBody) { 29 | this.mMultipartBody = multipartBody; 30 | } 31 | 32 | public ExMultipartBody(MultipartBody multipartBody, OnProgressListener progressListener) { 33 | this.mMultipartBody = multipartBody; 34 | this.mProgressListener = progressListener; 35 | } 36 | 37 | @Override 38 | public MediaType contentType() { 39 | return mMultipartBody.contentType(); 40 | } 41 | 42 | @Override 43 | public long contentLength() throws IOException { 44 | return mMultipartBody.contentLength(); 45 | } 46 | 47 | @Override 48 | public void writeTo(BufferedSink sink) throws IOException { 49 | 50 | 51 | //这里需要另一个代理类来获取写入的长度 52 | ForwardingSink forwardingSink = new ForwardingSink(sink) { 53 | 54 | final long totalLength = contentLength(); 55 | @Override 56 | public void write(Buffer source, long byteCount) throws IOException { 57 | //这里可以获取到写入的长度 58 | mCurrentLength += byteCount; 59 | //回调进度 60 | if (mProgressListener != null) { 61 | mProgressListener.onProgress(totalLength, mCurrentLength); 62 | } 63 | super.write(source, byteCount); 64 | } 65 | }; 66 | //转一下 67 | BufferedSink bufferedSink = Okio.buffer(forwardingSink); 68 | //写数据 69 | mMultipartBody.writeTo(bufferedSink); 70 | //刷新一下数据 71 | bufferedSink.flush(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.ContentUris; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.database.Cursor; 8 | import android.net.Uri; 9 | import android.os.Build; 10 | import android.os.Environment; 11 | import android.provider.DocumentsContract; 12 | import android.provider.MediaStore; 13 | import android.support.v4.content.FileProvider; 14 | import android.util.Log; 15 | 16 | 17 | import com.heyn.erosplugin.wx_filemanger.Application; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.ByteArrayOutputStream; 21 | import java.io.File; 22 | import java.io.FileOutputStream; 23 | import java.io.FileWriter; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.io.InputStreamReader; 27 | import java.io.PrintWriter; 28 | import java.math.BigDecimal; 29 | import java.util.ArrayList; 30 | import java.util.List; 31 | 32 | /** 33 | * Author: 崔海营 34 | * Date: 2018/9/19 35 | *

36 | * Introduce: 文件操作的工具类 37 | */ 38 | public class FileUtil { 39 | static InputStream in; 40 | static BufferedReader br; 41 | public static final String PACKAGE_NAME = 42 | Application.getAppContext().getPackageName() + ".fileProvider"; 43 | 44 | public static Intent openFile(String filePath) { 45 | File file = new File(filePath); 46 | if (!file.exists()) return null; 47 | /* 取得扩展名 */ 48 | String end = file.getName().substring(file.getName().lastIndexOf(".") + 1, file.getName().length()).toLowerCase(); 49 | /* 依扩展名的类型决定MimeType */ 50 | if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") || 51 | end.equals("xmf") || end.equals("ogg") || end.equals("wav")) { 52 | return getAudioFileIntent(filePath); 53 | } else if (end.equals("3gp") || end.equals("mp4")) { 54 | return getVideoFileIntent(filePath); 55 | } else if (end.equals("jpg") || end.equals("gif") || end.equals("png") || 56 | end.equals("jpeg") || end.equals("bmp")) { 57 | return getImageFileIntent(filePath); 58 | } else if (end.equals("apk")) { 59 | return getApkFileIntent(filePath); 60 | } else if (end.equals("ppt")) { 61 | return getPptFileIntent(filePath); 62 | } else if (end.equals("xls") || end.equals("xlsx")) { 63 | return getExcelFileIntent(filePath); 64 | } else if (end.equals("doc")) { 65 | return getWordFileIntent(filePath); 66 | } else if (end.equals("pdf")) { 67 | return getPdfFileIntent(filePath); 68 | } else if (end.equals("chm")) { 69 | return getChmFileIntent(filePath); 70 | } else if (end.equals("txt")) { 71 | return getTextFileIntent(filePath, false); 72 | } else { 73 | return getAllIntent(filePath); 74 | } 75 | } 76 | 77 | //Android获取一个用于打开APK文件的intent 78 | public static Intent getAllIntent(String param) { 79 | 80 | Intent intent = new Intent(); 81 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 82 | intent.setAction(Intent.ACTION_VIEW); 83 | Uri uri = getAndroidUri(param); 84 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 85 | intent.setDataAndType(uri, "*/*"); 86 | return intent; 87 | } 88 | 89 | //Android获取一个用于打开APK文件的intent 90 | public static Intent getApkFileIntent(String param) { 91 | Intent intent = new Intent(); 92 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 93 | intent.setAction(Intent.ACTION_VIEW); 94 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 95 | File file = new File(param); 96 | if (file.exists()) { 97 | Uri uri = getAndroidUri(param); 98 | intent.setDataAndType(uri, "application/vnd.android.package-archive"); 99 | } 100 | return intent; 101 | } 102 | 103 | //Android获取一个用于打开VIDEO文件的intent 104 | public static Intent getVideoFileIntent(String param) { 105 | 106 | Intent intent = new Intent("android.intent.action.VIEW"); 107 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 108 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 109 | intent.putExtra("oneshot", 0); 110 | intent.putExtra("configchange", 0); 111 | Uri uri = getAndroidUri(param); 112 | intent.setDataAndType(uri, "video/*"); 113 | return intent; 114 | } 115 | 116 | //Android获取一个用于打开AUDIO文件的intent 117 | public static Intent getAudioFileIntent(String param) { 118 | 119 | Intent intent = new Intent("android.intent.action.VIEW"); 120 | intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 121 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 122 | intent.putExtra("oneshot", 0); 123 | intent.putExtra("configchange", 0); 124 | Uri uri = getAndroidUri(param); 125 | intent.setDataAndType(uri, "audio/*"); 126 | return intent; 127 | } 128 | 129 | //Android获取一个用于打开Html文件的intent 130 | public static Intent getHtmlFileIntent(String param) { 131 | 132 | Uri uri = Uri.parse(param).buildUpon().encodedAuthority("com.android.htmlfileprovider").scheme("content").encodedPath(param).build(); 133 | Intent intent = new Intent("android.intent.action.VIEW"); 134 | intent.setDataAndType(uri, "text/html"); 135 | return intent; 136 | } 137 | 138 | //Android获取一个用于打开图片文件的intent 139 | public static Intent getImageFileIntent(String param) { 140 | Intent intent = new Intent("android.intent.action.VIEW"); 141 | intent.addCategory("android.intent.category.DEFAULT"); 142 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 143 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 144 | Uri uri = getAndroidUri(param); 145 | intent.setDataAndType(uri, "image/*"); 146 | return intent; 147 | } 148 | 149 | //Android获取一个用于打开PPT文件的intent 150 | public static Intent getPptFileIntent(String param) { 151 | 152 | Intent intent = new Intent("android.intent.action.VIEW"); 153 | intent.addCategory("android.intent.category.DEFAULT"); 154 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 155 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 156 | Uri uri = getAndroidUri(param); 157 | intent.setDataAndType(uri, "application/vnd.ms-powerpoint"); 158 | return intent; 159 | } 160 | 161 | //Android获取一个用于打开Excel文件的intent 162 | public static Intent getExcelFileIntent(String param) { 163 | 164 | Intent intent = new Intent("android.intent.action.VIEW"); 165 | intent.addCategory("android.intent.category.DEFAULT"); 166 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 167 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 168 | Uri uri = getAndroidUri(param); 169 | intent.setDataAndType(uri, "application/vnd.ms-excel"); 170 | return intent; 171 | } 172 | 173 | //Android获取一个用于打开Word文件的intent 174 | public static Intent getWordFileIntent(String param) { 175 | 176 | Intent intent = new Intent("android.intent.action.VIEW"); 177 | intent.addCategory("android.intent.category.DEFAULT"); 178 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 179 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 180 | Uri uri = getAndroidUri(param); 181 | intent.setDataAndType(uri, "application/msword"); 182 | return intent; 183 | } 184 | 185 | //Android获取一个用于打开CHM文件的intent 186 | public static Intent getChmFileIntent(String param) { 187 | 188 | Intent intent = new Intent("android.intent.action.VIEW"); 189 | intent.addCategory("android.intent.category.DEFAULT"); 190 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 191 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 192 | Uri uri = getAndroidUri(param); 193 | intent.setDataAndType(uri, "application/x-chm"); 194 | return intent; 195 | } 196 | 197 | //Android获取一个用于打开文本文件的intent 198 | public static Intent getTextFileIntent(String param, boolean paramBoolean) { 199 | 200 | Intent intent = new Intent("android.intent.action.VIEW"); 201 | intent.addCategory("android.intent.category.DEFAULT"); 202 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 203 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 204 | Uri uri = getAndroidUri(param, paramBoolean); 205 | intent.setDataAndType(uri, "text/plain"); 206 | return intent; 207 | } 208 | 209 | //Android获取一个用于打开PDF文件的intent 210 | public static Intent getPdfFileIntent(String param) { 211 | 212 | Intent intent = new Intent("android.intent.action.VIEW"); 213 | intent.addCategory("android.intent.category.DEFAULT"); 214 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 215 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 216 | Uri uri = getAndroidUri(param); 217 | intent.setDataAndType(uri, "application/pdf"); 218 | return intent; 219 | } 220 | 221 | /** 222 | * 获取版本对应的uri 223 | * 224 | * @param param 225 | * @return 226 | */ 227 | public static Uri getAndroidUri(String param) { 228 | Uri uri; 229 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { 230 | uri = FileProvider.getUriForFile( 231 | Application.getAppContext(), 232 | PACKAGE_NAME, 233 | new File(param)); 234 | } else { 235 | uri = Uri.fromFile(new File(param)); 236 | } 237 | return uri; 238 | } 239 | 240 | /** 241 | * text 对应的Uri获取 242 | * 243 | * @param param 244 | * @param paramBoolean 245 | * @return 246 | */ 247 | public static Uri getAndroidUri(String param, boolean paramBoolean) { 248 | Uri uri; 249 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { 250 | uri = FileProvider.getUriForFile( 251 | Application.getAppContext(), 252 | PACKAGE_NAME, 253 | new File(param)); 254 | } else { 255 | if (paramBoolean) { 256 | uri = Uri.parse(param); 257 | } else { 258 | uri = Uri.fromFile(new File(param)); 259 | } 260 | } 261 | return uri; 262 | } 263 | 264 | /** 265 | * 保存到SD卡 266 | * 267 | * @param filename 268 | * @param content 269 | * @throws Exception 270 | */ 271 | public static String saveToSDCard(String filename, byte[] content) throws Exception { 272 | String filePath = Environment.getExternalStorageDirectory() + "/chem"; 273 | File dirFirstFolder = new File(filePath); 274 | if (!dirFirstFolder.exists()) { 275 | //创建文件夹 276 | dirFirstFolder.mkdirs(); 277 | } 278 | File file = new File(filePath, filename); 279 | FileOutputStream outStream = new FileOutputStream(file); 280 | outStream.write(content); 281 | outStream.close(); 282 | return Environment.getExternalStorageDirectory() + "/chem/" + filename; 283 | } 284 | 285 | public static String saveToSDCard(String filename, InputStream in) throws IOException { 286 | String filePath = Environment.getExternalStorageDirectory() + "/YueYeYa"; 287 | File dirFirstFolder = new File(filePath); 288 | if (!dirFirstFolder.exists()) { 289 | //创建文件夹 290 | dirFirstFolder.mkdirs(); 291 | } 292 | File file = new File(filePath, filename); 293 | FileOutputStream outStream = new FileOutputStream(file); 294 | byte[] data = new byte[500]; 295 | int count = -1; 296 | while ((count = in.read(data, 0, 500)) != -1) { 297 | outStream.write(data, 0, count); 298 | } 299 | outStream.close(); 300 | in.close(); 301 | return Environment.getExternalStorageDirectory() + "/YueYeYa/" + filename; 302 | } 303 | 304 | public static String saveToSDCard(String filePath, String filename, InputStream in) throws IOException { 305 | File dirFirstFolder = new File(filePath); 306 | if (!dirFirstFolder.exists()) { 307 | //创建文件夹 308 | dirFirstFolder.mkdirs(); 309 | } 310 | File file = new File(filePath, filename); 311 | FileOutputStream outStream = new FileOutputStream(file); 312 | byte[] data = new byte[500]; 313 | int count = -1; 314 | while ((count = in.read(data, 0, 500)) != -1) { 315 | outStream.write(data, 0, count); 316 | } 317 | outStream.close(); 318 | in.close(); 319 | return file.getAbsolutePath(); 320 | } 321 | 322 | public static byte[] InputStreamTOByte(InputStream in) throws IOException { 323 | 324 | ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 325 | byte[] data = new byte[1024]; 326 | int count = -1; 327 | while ((count = in.read(data, 0, in.available())) != -1) 328 | outStream.write(data, 0, count); 329 | 330 | outStream.close(); 331 | return outStream.toByteArray(); 332 | } 333 | 334 | /** 335 | * 读取表情配置文件 336 | * 337 | * @param context 338 | * @return 339 | */ 340 | public static List getEmojiFile(Context context) { 341 | try { 342 | List list = new ArrayList(); 343 | in = context.getResources().getAssets().open("emoji"); 344 | br = new BufferedReader(new InputStreamReader(in, 345 | "UTF-8")); 346 | String str = null; 347 | while ((str = br.readLine()) != null) { 348 | list.add(str); 349 | } 350 | 351 | return list; 352 | } catch (IOException e) { 353 | e.printStackTrace(); 354 | } 355 | return null; 356 | } 357 | 358 | /** 359 | * 关闭IO流 360 | */ 361 | public static void close() { 362 | if (br != null) { 363 | try { 364 | br.close(); 365 | br = null; 366 | Log.d("close", "br"); 367 | } catch (IOException e) { 368 | e.printStackTrace(); 369 | } 370 | } 371 | if (in != null) { 372 | try { 373 | in.close(); 374 | in = null; 375 | Log.d("close", "in"); 376 | } catch (IOException e) { 377 | e.printStackTrace(); 378 | } 379 | } 380 | } 381 | 382 | /** 383 | * 根据资源名获取ID 384 | * 385 | * @param fileName 资源文件名称 386 | * @param context 387 | * @return 388 | */ 389 | public static int getResourceId(String fileName, Context context) { 390 | String imageName = fileName 391 | .substring(0, fileName.lastIndexOf(".")); 392 | int resId = context.getResources().getIdentifier(imageName, "drawable", context.getPackageName()); 393 | //如果没有在"drawable"下找到imageName,将会返回0 394 | Log.d("id", String.valueOf(resId)); 395 | return resId; 396 | } 397 | 398 | /** 399 | * SDk 版本小于于4.4时,Uri 转换成真实路径的方法 400 | * 401 | * @param context 402 | * @param uri 403 | * @return 404 | */ 405 | public static String getPathByUriOld(Context context, Uri uri) { 406 | String filename = null; 407 | if (uri.getScheme().toString().compareTo("content") == 0) { 408 | Cursor cursor = context.getContentResolver().query(uri, new String[]{"_data"}, null, null, null); 409 | if (cursor.moveToFirst()) { 410 | filename = cursor.getString(0); 411 | } 412 | } else if (uri.getScheme().toString().compareTo("file") == 0) {// file:///开头的uri 413 | filename = uri.toString(); 414 | filename = uri.toString().replace("file://", "");// 替换file:// 415 | if (!filename.startsWith("/mnt")) {// 加上"/mnt"头 416 | filename += "/mnt"; 417 | } 418 | } 419 | return filename; 420 | } 421 | 422 | /** 423 | * SDk 版本大于4.4时,Uri 转换成真实路径的方法 424 | * 425 | * @param context 426 | * @param uri 427 | * @return 428 | */ 429 | @SuppressLint("NewApi") //作用仅仅是屏蔽android lint错误,所以在方法中还要判断版本做不同的操作. 430 | public static String getPathByUrikitkat(final Context context, final Uri uri) { 431 | final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; 432 | // DocumentProvider 433 | if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { 434 | if (isExternalStorageDocument(uri)) {// ExternalStorageProvider 435 | final String docId = DocumentsContract.getDocumentId(uri); 436 | final String[] split = docId.split(":"); 437 | final String type = split[0]; 438 | if ("primary".equalsIgnoreCase(type)) { 439 | return Environment.getExternalStorageDirectory() + "/" + split[1]; 440 | } 441 | } else if (isDownloadsDocument(uri)) {// DownloadsProvider 442 | final String id = DocumentsContract.getDocumentId(uri); 443 | final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), 444 | Long.valueOf(id)); 445 | return getDataColumn(context, contentUri, null, null); 446 | } else if (isMediaDocument(uri)) {// MediaProvider 447 | final String docId = DocumentsContract.getDocumentId(uri); 448 | final String[] split = docId.split(":"); 449 | final String type = split[0]; 450 | Uri contentUri = null; 451 | if ("image".equals(type)) { 452 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 453 | } else if ("video".equals(type)) { 454 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; 455 | } else if ("audio".equals(type)) { 456 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; 457 | } 458 | final String selection = "_id=?"; 459 | final String[] selectionArgs = new String[]{split[1]}; 460 | return getDataColumn(context, contentUri, selection, selectionArgs); 461 | } 462 | } else if ("content".equalsIgnoreCase(uri.getScheme())) { 463 | if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M && isAndroidNUri(uri)) { 464 | final String[] split = uri.getPath().split("/"); 465 | StringBuilder path = new StringBuilder(""); 466 | boolean begin = false; 467 | for (int i = 0; i < split.length; i++) { 468 | if (!begin && split[i].equals("storage")) { 469 | begin = true; 470 | } 471 | if (begin) { 472 | path.append("/"); 473 | path.append(split[i]); 474 | } 475 | } 476 | return path.toString(); 477 | } 478 | return getDataColumn(context, uri, null, null); 479 | } else if ("file".equalsIgnoreCase(uri.getScheme())) { 480 | return uri.getPath(); 481 | } 482 | return null; 483 | } 484 | 485 | private static boolean isAndroidNUri(Uri uri) { 486 | return "com.fihtdc.filemanager.provider".equals(uri.getAuthority()); 487 | } 488 | 489 | public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) { 490 | Cursor cursor = null; 491 | final String column = "_data"; 492 | final String[] projection = {column}; 493 | try { 494 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); 495 | if (cursor != null && cursor.moveToFirst()) { 496 | final int column_index = cursor.getColumnIndexOrThrow(column); 497 | return cursor.getString(column_index); 498 | } 499 | } finally { 500 | if (cursor != null) 501 | cursor.close(); 502 | } 503 | return null; 504 | } 505 | 506 | public static boolean isExternalStorageDocument(Uri uri) { 507 | return "com.android.externalstorage.documents".equals(uri.getAuthority()); 508 | } 509 | 510 | public static boolean isDownloadsDocument(Uri uri) { 511 | return "com.android.providers.downloads.documents".equals(uri.getAuthority()); 512 | } 513 | 514 | public static boolean isMediaDocument(Uri uri) { 515 | return "com.android.providers.media.documents".equals(uri.getAuthority()); 516 | } 517 | 518 | 519 | /** 520 | * 保存JSON文件 521 | * 522 | * @return 523 | */ 524 | public static String saveJson(Context context, String json) { 525 | String path; 526 | if (hasSdCard()) { 527 | path = context.getExternalFilesDir("").toString(); 528 | } else { 529 | path = context.getFilesDir().toString(); 530 | } 531 | File file = new File(path, "user_group.json"); 532 | try { 533 | writeFile(file.getPath(), json); 534 | Log.d("jsonStatus", "保存本地成功!"); 535 | } catch (IOException e) { 536 | e.printStackTrace(); 537 | } 538 | return file.getPath(); 539 | } 540 | 541 | public static void writeFile(String filePath, String sets) throws IOException { 542 | FileWriter fw = new FileWriter(filePath); 543 | PrintWriter out = new PrintWriter(fw); 544 | out.write(sets); 545 | out.println(); 546 | fw.close(); 547 | out.close(); 548 | } 549 | 550 | public static boolean hasSdCard() { 551 | String sdStatus = Environment.getExternalStorageState(); 552 | if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { 553 | return false; 554 | } 555 | return true; 556 | } 557 | 558 | /** 559 | * 获取文件的类型 560 | * 561 | * @param filePath 562 | * @return 563 | */ 564 | public static int mediaType(String filePath) { 565 | if (filePath != null) { 566 | String end = filePath.substring(filePath.lastIndexOf(".") + 1, filePath.length()).toLowerCase(); 567 | /* 依扩展名的类型决定MimeType */ 568 | if (end.equals("m4a") || end.equals("mp3") || end.equals("mid") || 569 | end.equals("xmf") || end.equals("ogg") || end.equals("wav")) { 570 | return 1; 571 | } else if (end.equals("3gp") || end.equals("mp4")) { 572 | return 2; 573 | } else if (end.equals("jpg") || end.equals("gif") || end.equals("png") || 574 | end.equals("jpeg") || end.equals("bmp")) { 575 | return 3; 576 | } else if (end.equals("apk")) { 577 | return 4; 578 | } else if (end.equals("ppt")) { 579 | return 5; 580 | } else if (end.equals("xls")) { 581 | return 6; 582 | } else if (end.equals("doc")) { 583 | return 7; 584 | } else if (end.equals("pdf")) { 585 | return 8; 586 | } else if (end.equals("chm")) { 587 | return 9; 588 | } else if (end.equals("txt")) { 589 | return 10; 590 | } else { 591 | return 11; 592 | } 593 | } else { 594 | return 0; 595 | } 596 | } 597 | 598 | /** 599 | * 获取文件名的后缀 600 | * 601 | * @param fileName 602 | * @return 603 | */ 604 | public static String getEndName(String fileName) { 605 | if (fileName.lastIndexOf(".") == -1) { 606 | return ""; 607 | } 608 | return fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()).toLowerCase(); 609 | } 610 | 611 | /** 612 | * 判断文件是否存在 613 | * 614 | * @return 615 | */ 616 | public static boolean isFileExist(String filePath) { 617 | File downloadFile = new File(filePath); 618 | return downloadFile.exists(); 619 | } 620 | 621 | /** 622 | * 计算某一文件的大小 623 | * 624 | * @param file 625 | * @return 626 | * @throws Exception 627 | */ 628 | public static long getFolderSize(File file) throws Exception { 629 | long size = 0; 630 | try { 631 | File[] fileList = file.listFiles(); 632 | for (int i = 0; i < fileList.length; i++) { 633 | // 如果下面还有文件 634 | if (fileList[i].isDirectory()) { 635 | size = size + getFolderSize(fileList[i]); 636 | } else { 637 | size = size + fileList[i].length(); 638 | } 639 | } 640 | } catch (Exception e) { 641 | e.printStackTrace(); 642 | } 643 | return size; 644 | } 645 | 646 | 647 | /** 648 | * 递归清空某一文件夹 649 | * 650 | * @param file 651 | */ 652 | public static void deleteFiles(File file) { 653 | if (file.exists()) { 654 | // 如果file是一个文件,直接删除 655 | if (file.isFile()) { 656 | file.delete(); 657 | return; 658 | } 659 | // 如果file是一个文件夹,遍历内部的文件和文件夹,递归删除 660 | if (file.isDirectory()) { 661 | File[] chileFiles = file.listFiles(); 662 | if (chileFiles == null || chileFiles.length == 0) { 663 | file.delete(); 664 | return; 665 | } 666 | for (File file1 : chileFiles) { 667 | deleteFiles(file1); 668 | } 669 | file.delete(); 670 | } 671 | } 672 | } 673 | 674 | /** 675 | * 格式化单位 676 | * 677 | * @param size 678 | * @return 679 | */ 680 | public static String getFormatSize(double size) { 681 | double kiloByte = size / 1024; 682 | if (kiloByte < 1) { 683 | return "0.0MB"; 684 | } 685 | 686 | double megaByte = kiloByte / 1024; 687 | if (megaByte < 1) { 688 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); 689 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP) 690 | .toPlainString() + "KB"; 691 | } 692 | 693 | double gigaByte = megaByte / 1024; 694 | if (gigaByte < 1) { 695 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); 696 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP) 697 | .toPlainString() + "MB"; 698 | } 699 | 700 | double teraBytes = gigaByte / 1024; 701 | if (teraBytes < 1) { 702 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); 703 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP) 704 | .toPlainString() + "GB"; 705 | } 706 | BigDecimal result4 = new BigDecimal(teraBytes); 707 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() 708 | + "TB"; 709 | } 710 | 711 | } 712 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/Md5Util.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.security.MessageDigest; 6 | 7 | /** 8 | * Author: Heynchy 9 | * Date: 2019/6/26 10 | *

11 | * Introduce: 12 | */ 13 | public class Md5Util { 14 | /** 15 | * 获取文件的MD5值 16 | * 17 | * @param file 18 | * @return 19 | */ 20 | public static String getFileMD5(File file) { 21 | if (!file.isFile()) { 22 | return null; 23 | } 24 | MessageDigest digest = null; 25 | FileInputStream in = null; 26 | byte buffer[] = new byte[1024]; 27 | int len; 28 | try { 29 | digest = MessageDigest.getInstance("MD5"); 30 | in = new FileInputStream(file); 31 | while ((len = in.read(buffer, 0, 1024)) != -1) { 32 | digest.update(buffer, 0, len); 33 | } 34 | in.close(); 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | return null; 38 | } 39 | return bytesToHexString(digest.digest()); 40 | } 41 | 42 | public static String bytesToHexString(byte[] src) { 43 | StringBuilder stringBuilder = new StringBuilder(""); 44 | if (src == null || src.length <= 0) { 45 | return null; 46 | } 47 | for (int i = 0; i < src.length; i++) { 48 | int v = src[i] & 0xFF; 49 | String hv = Integer.toHexString(v); 50 | if (hv.length() < 2) { 51 | stringBuilder.append(0); 52 | } 53 | stringBuilder.append(hv); 54 | } 55 | return stringBuilder.toString(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/PermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | 4 | import android.Manifest; 5 | import android.app.Activity; 6 | import android.content.pm.PackageManager; 7 | import android.support.v4.app.ActivityCompat; 8 | 9 | /** 10 | * Author: 崔海营 11 | * Date: 2018/9/19 12 | *

13 | * Introduce: Android 6.0 内存卡权限读取工具类 14 | */ 15 | 16 | public class PermissionUtil { 17 | // Storage Permissions 18 | public static final int REQUEST_EXTERNAL_STORAGE = 1; 19 | private static String[] PERMISSIONS_STORAGE = { 20 | Manifest.permission.READ_EXTERNAL_STORAGE, 21 | Manifest.permission.WRITE_EXTERNAL_STORAGE}; 22 | 23 | /** 24 | * 判断是否拥有内存卡读取权限 25 | * 26 | * @param activity 27 | * @return 28 | */ 29 | public static boolean hasStoragePermission(Activity activity) { 30 | int permission = ActivityCompat.checkSelfPermission(activity, 31 | Manifest.permission.READ_EXTERNAL_STORAGE); 32 | if (permission != PackageManager.PERMISSION_GRANTED) { 33 | return false; 34 | } else { 35 | return true; 36 | } 37 | } 38 | 39 | /** 40 | * 获取内存卡读取权限 41 | */ 42 | public static void getStoragePermissions(Activity activity) { 43 | ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, 44 | REQUEST_EXTERNAL_STORAGE); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/PixInfoUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * Author: 崔海营 7 | * Date: 2018/10/9 8 | *

9 | * Introduce: 10 | */ 11 | public class PixInfoUtil { 12 | /** 13 | * dp转换成px 14 | */ 15 | public static int dpTopx(Context context, int dp) { 16 | return (int) (context.getResources().getDisplayMetrics().density * dp + 0.5f); 17 | } 18 | 19 | /** 20 | * px转换成dp 21 | */ 22 | public static int px2dp(Context context, float pxValue) { 23 | float scale = context.getResources().getDisplayMetrics().density; 24 | return (int) (pxValue / scale + 0.5f); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/SPUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.util.Map; 9 | 10 | /** 11 | * Author: Heynchy 12 | * Date: 2018/9/19 13 | *

14 | * Introduce: 本地存储的工具类 15 | */ 16 | public class SPUtil { 17 | public SPUtil() { 18 | // cannot be instantiated 19 | throw new UnsupportedOperationException("cannot be instantiated"); 20 | } 21 | 22 | /** 23 | * sharepreference`s file name. 24 | */ 25 | public static final String FILE_NAME = "chem_data"; 26 | 27 | /** 28 | * Save data .we should get data`s type,and then,auto-call diff function. 29 | * 30 | * @param context 31 | * @param key 32 | * @param object Must has concrete type. 33 | */ 34 | public static void put(Context context, String key, Object object) { 35 | 36 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 37 | Context.MODE_PRIVATE); 38 | SharedPreferences.Editor editor = sp.edit(); 39 | if (object instanceof String) { 40 | editor.putString(key, (String) object); 41 | } else if (object instanceof Integer) { 42 | editor.putInt(key, (Integer) object); 43 | } else if (object instanceof Boolean) { 44 | editor.putBoolean(key, (Boolean) object); 45 | } else if (object instanceof Float) { 46 | editor.putFloat(key, (Float) object); 47 | } else if (object instanceof Long) { 48 | editor.putLong(key, (Long) object); 49 | } else { 50 | editor.putString(key, object.toString()); 51 | } 52 | SharedPreferencesCompat.apply(editor); 53 | } 54 | 55 | 56 | /** 57 | * Save data .we should get data`s type,and then,auto-call diff function. 58 | * 59 | * @param context 60 | * @param key 61 | * @param object Must has concrete type. 62 | */ 63 | public static void put(Context context, String fileName, String key, Object object) { 64 | 65 | SharedPreferences sp = context.getSharedPreferences(fileName, 66 | Context.MODE_PRIVATE); 67 | SharedPreferences.Editor editor = sp.edit(); 68 | 69 | if (object instanceof String) { 70 | editor.putString(key, (String) object); 71 | } else if (object instanceof Integer) { 72 | editor.putInt(key, (Integer) object); 73 | } else if (object instanceof Boolean) { 74 | editor.putBoolean(key, (Boolean) object); 75 | } else if (object instanceof Float) { 76 | editor.putFloat(key, (Float) object); 77 | } else if (object instanceof Long) { 78 | editor.putLong(key, (Long) object); 79 | } else { 80 | editor.putString(key, object.toString()); 81 | } 82 | SharedPreferencesCompat.apply(editor); 83 | } 84 | 85 | /** 86 | * Obtain data.funciton can auto-judge type through defaultObject. 87 | * 88 | * @param context 89 | * @param key 90 | * @param defaultObject 91 | * @return 92 | */ 93 | public static Object get(Context context, String key, Object defaultObject) { 94 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 95 | Context.MODE_PRIVATE); 96 | 97 | if (defaultObject instanceof String) { 98 | return sp.getString(key, (String) defaultObject); 99 | } else if (defaultObject instanceof Integer) { 100 | return sp.getInt(key, (Integer) defaultObject); 101 | } else if (defaultObject instanceof Boolean) { 102 | return sp.getBoolean(key, (Boolean) defaultObject); 103 | } else if (defaultObject instanceof Float) { 104 | return sp.getFloat(key, (Float) defaultObject); 105 | } else if (defaultObject instanceof Long) { 106 | return sp.getLong(key, (Long) defaultObject); 107 | } 108 | 109 | return null; 110 | } 111 | 112 | /** 113 | * Obtain data.funciton can auto-judge type through defaultObject. 114 | * 115 | * @param context 116 | * @param key 117 | * @param defaultObject 118 | * @return 119 | */ 120 | public static Object get(Context context, String fileName, String key, Object defaultObject) { 121 | SharedPreferences sp = context.getSharedPreferences(fileName, 122 | Context.MODE_PRIVATE); 123 | 124 | if (defaultObject instanceof String) { 125 | return sp.getString(key, (String) defaultObject); 126 | } else if (defaultObject instanceof Integer) { 127 | return sp.getInt(key, (Integer) defaultObject); 128 | } else if (defaultObject instanceof Boolean) { 129 | return sp.getBoolean(key, (Boolean) defaultObject); 130 | } else if (defaultObject instanceof Float) { 131 | return sp.getFloat(key, (Float) defaultObject); 132 | } else if (defaultObject instanceof Long) { 133 | return sp.getLong(key, (Long) defaultObject); 134 | } 135 | 136 | return null; 137 | } 138 | 139 | 140 | /** 141 | * Remove value through key. 142 | * 143 | * @param context 144 | * @param key 145 | */ 146 | public static void remove(Context context, String key) { 147 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 148 | Context.MODE_PRIVATE); 149 | SharedPreferences.Editor editor = sp.edit(); 150 | editor.remove(key); 151 | SharedPreferencesCompat.apply(editor); 152 | } 153 | 154 | /** 155 | * Clear data. 156 | * 157 | * @param context 158 | */ 159 | public static void clear(Context context) { 160 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 161 | Context.MODE_PRIVATE); 162 | SharedPreferences.Editor editor = sp.edit(); 163 | editor.clear(); 164 | SharedPreferencesCompat.apply(editor); 165 | } 166 | 167 | /** 168 | * Check where the key is exist. 169 | * 170 | * @param context 171 | * @param key 172 | * @return 173 | */ 174 | public static boolean contains(Context context, String key) { 175 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 176 | Context.MODE_PRIVATE); 177 | return sp.contains(key); 178 | } 179 | 180 | /** 181 | * Obtain all key-values 182 | * 183 | * @param context 184 | * @return 185 | */ 186 | public static Map getAll(Context context) { 187 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, 188 | Context.MODE_PRIVATE); 189 | return sp.getAll(); 190 | } 191 | 192 | /** 193 | * SharedPreferencesCompat.apply compatible class. 194 | */ 195 | private static class SharedPreferencesCompat { 196 | private static final Method sApplyMethod = findApplyMethod(); 197 | 198 | /** 199 | * Reflection method for finding apply 200 | * 201 | * @return 202 | */ 203 | @SuppressWarnings({"unchecked", "rawtypes"}) 204 | private static Method findApplyMethod() { 205 | try { 206 | Class clz = SharedPreferences.Editor.class; 207 | return clz.getMethod("apply"); 208 | } catch (NoSuchMethodException e) { 209 | } 210 | 211 | return null; 212 | } 213 | 214 | /** 215 | * If find,use apply excute,else use commit. 216 | * 217 | * @param editor 218 | */ 219 | public static void apply(SharedPreferences.Editor editor) { 220 | try { 221 | if (sApplyMethod != null) { 222 | sApplyMethod.invoke(editor); 223 | return; 224 | } 225 | } catch (IllegalArgumentException e) { 226 | } catch (IllegalAccessException e) { 227 | } catch (InvocationTargetException e) { 228 | } 229 | editor.commit(); 230 | } 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/java/com/heyn/erosplugin/wx_filemanger/util/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger.util; 2 | 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.widget.Toast; 6 | 7 | import com.heyn.erosplugin.wx_filemanger.Application; 8 | 9 | 10 | /** 11 | * Author: 崔海营 12 | * Date: 2018/9/19 13 | *

14 | * Introduce: Toast提示的工具类 15 | */ 16 | public class ToastUtil { 17 | 18 | private static volatile ToastUtil sToastUtil = null; 19 | 20 | private Toast mToast = null; 21 | 22 | /** 23 | * 获取实例 24 | * 25 | * @return 26 | */ 27 | public static ToastUtil getInstance() { 28 | if (sToastUtil == null) { 29 | synchronized (ToastUtil.class) { 30 | if (sToastUtil == null) { 31 | sToastUtil = new ToastUtil(); 32 | } 33 | } 34 | } 35 | return sToastUtil; 36 | } 37 | 38 | protected Handler handler = new Handler(Looper.getMainLooper()); 39 | 40 | /** 41 | * 显示Toast,多次调用此函数时,Toast显示的时间不会累计,并且显示内容为最后一次调用时传入的内容 42 | * 持续时间默认为short 43 | * 44 | * @param tips 要显示的内容 45 | * {@link Toast#LENGTH_LONG} 46 | */ 47 | public void showToast(final String tips) { 48 | showToast(tips, Toast.LENGTH_SHORT); 49 | } 50 | 51 | public void showToast(final int tips) { 52 | showToast(tips, Toast.LENGTH_SHORT); 53 | } 54 | 55 | /** 56 | * 显示Toast,多次调用此函数时,Toast显示的时间不会累计,并且显示内容为最后一次调用时传入的内容 57 | * 58 | * @param tips 要显示的内容 59 | * @param duration 持续时间,参见{@link Toast#LENGTH_SHORT}和 60 | * {@link Toast#LENGTH_LONG} 61 | */ 62 | public void showToast(final String tips, final int duration) { 63 | if (android.text.TextUtils.isEmpty(tips)) { 64 | return; 65 | } 66 | handler.post(new Runnable() { 67 | @Override 68 | public void run() { 69 | if (mToast == null) { 70 | mToast = Toast.makeText(Application.getAppContext(), tips, duration); 71 | mToast.show(); 72 | } else { 73 | //mToast.cancel(); 74 | //mToast.setView(mToast.getView()); 75 | mToast.setText(tips); 76 | mToast.setDuration(duration); 77 | mToast.show(); 78 | } 79 | } 80 | }); 81 | } 82 | 83 | public void showToast(final int tips, final int duration) { 84 | handler.post(new Runnable() { 85 | @Override 86 | public void run() { 87 | if (mToast == null) { 88 | mToast = Toast.makeText(Application.getAppContext(), tips, duration); 89 | mToast.show(); 90 | } else { 91 | //mToast.cancel(); 92 | //mToast.setView(mToast.getView()); 93 | mToast.setText(tips); 94 | mToast.setDuration(duration); 95 | mToast.show(); 96 | } 97 | } 98 | }); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 没有找到打开该类型文件的应用 5 | 该文件不存在 6 | 0.0MB 7 | 8 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /wx_filemanager/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /wx_filemanager/src/test/java/com/heyn/erosplugin/wx_filemanger/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.heyn.erosplugin.wx_filemanger; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } --------------------------------------------------------------------------------