From 09481127c29e5b8d1b07779984e3aefdf1ebc2c1 Mon Sep 17 00:00:00 2001 From: lele <879860859@qq.com> Date: Mon, 24 May 2021 18:59:54 +0800 Subject: [PATCH 1/6] first commit --- .gitignore | 10 +- .idea/gradle.xml | 20 -- .idea/misc.xml | 44 --- LICENSE | 6 +- README.OPENSOURCE | 10 + README.md | 273 ++++++++++------- {example-client => entry}/.gitignore | 0 entry/build.gradle | 32 ++ entry/src/main/config.json | 67 +++++ .../stompclientexample/EchoModel.java | 6 + .../stompclientexample/ExampleRepository.java | 11 +- .../stompclientexample/MainAbility.java | 18 ++ .../stompclientexample/MyApplication.java | 15 + .../stompclientexample/RestClient.java | 59 +++- .../stompclientexample/SimpleAdapter.java | 77 +++++ .../layout/BaseDirectionalLayout.java | 153 ++++++++++ .../layout/FinalStaticBean.java | 275 ++++++++++++++++++ .../stompclientexample/layout/ToastUtil.java | 122 ++++++++ .../rxHarmony/OpenHandlerScheduler.java | 130 +++++++++ .../rxHarmony/OpenHarmonySchedulers.java | 63 ++++ .../rxHarmony/RxHmOSPlugins.java | 111 +++++++ .../slice/MainAbilitySlice.java | 250 +++++++++++----- .../stompclientexample/utils/ToastUtil.java | 134 +++++++++ .../main/resources/base/element/color.json | 185 ++++++++++++ .../main/resources/base/element/string.json | 28 ++ .../base/graphic/background_ability_main.xml | 6 + .../base/graphic/toast_background_shape.xml | 8 + .../resources/base/layout/ability_main.xml | 122 ++++++++ .../resources/base/layout/item_layout.xml | 19 ++ .../base/layout/toast_dialog_layout.xml | 22 ++ entry/src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../stompclientexample/ExampleTest.java | 37 +++ example-client/README.md | 3 - example-client/build.gradle | 59 ---- example-client/gradle.properties | 2 - example-client/proguard-rules.pro | 17 -- example-client/src/main/AndroidManifest.xml | 24 -- .../stompclientexample/SimpleAdapter.java | 52 ---- .../src/main/res/layout/activity_main.xml | 75 ----- .../src/main/res/layout/item_layout.xml | 19 -- .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3418 -> 0 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2206 -> 0 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4842 -> 0 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7718 -> 0 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10486 -> 0 bytes .../src/main/res/values-w820dp/dimens.xml | 6 - example-client/src/main/res/values/colors.xml | 6 - example-client/src/main/res/values/dimens.xml | 5 - .../src/main/res/values/strings.xml | 7 - example-client/src/main/res/values/styles.xml | 11 - .../main/res/xml/network_security_config.xml | 6 - gradlew | 114 +++++--- gradlew.bat | 33 ++- lib/build.gradle | 73 +---- lib/libs/okhttp.jar | Bin 0 -> 628291 bytes lib/src/main/config.json | 27 ++ .../ua/naiksoftware/stomp/HeartBeatTask.java | 134 ++++++--- .../java/ua/naiksoftware/stomp/Stomp.java | 54 +++- .../ua/naiksoftware/stomp/StompClient.java | 216 +++++++++----- .../stomp/dto/LifecycleEvent.java | 36 ++- .../naiksoftware/stomp/dto/StompCommand.java | 30 +- .../naiksoftware/stomp/dto/StompHeader.java | 33 ++- .../naiksoftware/stomp/dto/StompMessage.java | 83 ++++-- .../stomp/pathmatcher/PathMatcher.java | 13 +- .../stomp/pathmatcher/RabbitPathMatcher.java | 47 +-- .../stomp/pathmatcher/SimplePathMatcher.java | 12 +- .../pathmatcher/SubscriptionPathMatcher.java | 27 +- .../provider/AbstractConnectionProvider.java | 40 ++- .../stomp/provider/ConnectionProvider.java | 9 +- .../provider/OkHttpConnectionProvider.java | 59 +++- .../WebSocketsConnectionProvider.java | 46 +-- .../main/resources/base/element/string.json | 8 + settings.gradle | 2 +- test-server/README.md | 5 - .../src/main/resources/application.properties | 8 - test_server/.gitignore | 1 + test_server/README.md | 7 + {test-server => test_server}/build.gradle | 7 +- .../ua/naiksoftware/test_server/Main.java | 8 +- .../test_server/config/WebSocketConfig.groovy | 0 .../controller/SocketController.groovy | 0 .../test_server/model/EchoModel.groovy | 0 .../test_server/service/SocketService.groovy | 0 83 files changed, 2822 insertions(+), 915 deletions(-) delete mode 100644 .idea/gradle.xml delete mode 100644 .idea/misc.xml create mode 100644 README.OPENSOURCE rename {example-client => entry}/.gitignore (100%) create mode 100644 entry/build.gradle create mode 100644 entry/src/main/config.json rename {example-client => entry}/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java (81%) rename {example-client => entry}/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java (69%) create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/MainAbility.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/MyApplication.java rename {example-client => entry}/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java (46%) create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/SimpleAdapter.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/layout/BaseDirectionalLayout.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/layout/FinalStaticBean.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/layout/ToastUtil.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHandlerScheduler.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHarmonySchedulers.java create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/RxHmOSPlugins.java rename example-client/src/main/java/ua/naiksoftware/stompclientexample/MainActivity.java => entry/src/main/java/ua/naiksoftware/stompclientexample/slice/MainAbilitySlice.java (39%) create mode 100644 entry/src/main/java/ua/naiksoftware/stompclientexample/utils/ToastUtil.java create mode 100644 entry/src/main/resources/base/element/color.json create mode 100644 entry/src/main/resources/base/element/string.json create mode 100644 entry/src/main/resources/base/graphic/background_ability_main.xml create mode 100644 entry/src/main/resources/base/graphic/toast_background_shape.xml create mode 100644 entry/src/main/resources/base/layout/ability_main.xml create mode 100644 entry/src/main/resources/base/layout/item_layout.xml create mode 100644 entry/src/main/resources/base/layout/toast_dialog_layout.xml create mode 100644 entry/src/main/resources/base/media/icon.png create mode 100644 entry/src/test/java/ua/naiksoftware/stompclientexample/ExampleTest.java delete mode 100644 example-client/README.md delete mode 100644 example-client/build.gradle delete mode 100644 example-client/gradle.properties delete mode 100644 example-client/proguard-rules.pro delete mode 100644 example-client/src/main/AndroidManifest.xml delete mode 100644 example-client/src/main/java/ua/naiksoftware/stompclientexample/SimpleAdapter.java delete mode 100644 example-client/src/main/res/layout/activity_main.xml delete mode 100644 example-client/src/main/res/layout/item_layout.xml delete mode 100644 example-client/src/main/res/mipmap-hdpi/ic_launcher.png delete mode 100644 example-client/src/main/res/mipmap-mdpi/ic_launcher.png delete mode 100644 example-client/src/main/res/mipmap-xhdpi/ic_launcher.png delete mode 100644 example-client/src/main/res/mipmap-xxhdpi/ic_launcher.png delete mode 100644 example-client/src/main/res/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 example-client/src/main/res/values-w820dp/dimens.xml delete mode 100644 example-client/src/main/res/values/colors.xml delete mode 100644 example-client/src/main/res/values/dimens.xml delete mode 100644 example-client/src/main/res/values/strings.xml delete mode 100644 example-client/src/main/res/values/styles.xml delete mode 100644 example-client/src/main/res/xml/network_security_config.xml create mode 100644 lib/libs/okhttp.jar create mode 100644 lib/src/main/config.json create mode 100644 lib/src/main/resources/base/element/string.json delete mode 100644 test-server/README.md delete mode 100644 test-server/src/main/resources/application.properties create mode 100644 test_server/.gitignore create mode 100644 test_server/README.md rename {test-server => test_server}/build.gradle (96%) rename test-server/src/main/groovy/ua/naiksoftware/test_server/Main.groovy => test_server/src/main/groovy/ua/naiksoftware/test_server/Main.java (67%) rename {test-server => test_server}/src/main/groovy/ua/naiksoftware/test_server/config/WebSocketConfig.groovy (100%) rename {test-server => test_server}/src/main/groovy/ua/naiksoftware/test_server/controller/SocketController.groovy (100%) rename {test-server => test_server}/src/main/groovy/ua/naiksoftware/test_server/model/EchoModel.groovy (100%) rename {test-server => test_server}/src/main/groovy/ua/naiksoftware/test_server/service/SocketService.groovy (100%) diff --git a/.gitignore b/.gitignore index a13729d..603b140 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,14 @@ *.iml .gradle /local.properties -.idea +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml .DS_Store /build /captures -test-server/build +.externalNativeBuild +.cxx diff --git a/.idea/gradle.xml b/.idea/gradle.xml deleted file mode 100644 index 804e5a0..0000000 --- a/.idea/gradle.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 6dfa535..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/LICENSE b/LICENSE index 03509f6..56ec647 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -The MIT License (MIT) +he MIT License (MIT) -Copyright (c) 2016 Nickolay Savchenko +Copyright (c) 2016 Nickolay Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +SOFTWARE. \ No newline at end of file diff --git a/README.OPENSOURCE b/README.OPENSOURCE new file mode 100644 index 0000000..19e3f5f --- /dev/null +++ b/README.OPENSOURCE @@ -0,0 +1,10 @@ +[ + { + "Name": "StompProtocolAndroid", + "License": "MIT License", + "License File": "LICENSE", + "Version Number": " master ", + "Upstream URL": "https://github.com/NaikSoftware/StompProtocolAndroid", + "Description": "通过适用于Android的WebSocket的STOMP协议实现了Android的长连接" + } +] \ No newline at end of file diff --git a/README.md b/README.md index 2c3c806..09e7992 100644 --- a/README.md +++ b/README.md @@ -1,119 +1,180 @@ -# STOMP protocol via WebSocket for Android - -[![Release](https://jitpack.io/v/NaikSoftware/StompProtocolAndroid.svg)](https://jitpack.io/#NaikSoftware/StompProtocolAndroid) - -## Overview - -This library provide support for STOMP protocol https://stomp.github.io/ -At now library works only as client for backend with support STOMP, such as -NodeJS (stompjs or other) or Spring Boot (SockJS). - -Add library as gradle dependency - +# StompProtocolOhos + +#### 项目介绍 +- 项目名称: StompProtocolOhos +- 所属系列:OpenHarmony的第三方组件适配移植 +- 功能:对STOMP协议支持长连接 收发消息 +- 项目移植状态:完成 +- 调用差异:无 +- 开发版本:sdk5,DevEco Studio2.1 beta4 +- 基线版本:基于原组件的Master分支 + +#### 安装教程 +1.在项目根目录下的build.gradle文件中, ```gradle -repositories { - jcenter() - maven { url "https://jitpack.io" } +allprojects { + repositories { + maven { + url 'https://s01.oss.sonatype.org/content/repositories/snapshots/' + } + } } +``` +2.在entry模块的build.gradle文件中, +```gradle dependencies { - implementation 'com.github.NaikSoftware:StompProtocolAndroid:{latest version}' + implementation('com.gitee.chinasoft_ohos:cutout:0.0.1-SNAPSHOT') + ...... } +在sdk5,DevEco Studio2.1 beta4下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下 ``` -## Example backend (Spring Boot) +#### 使用说明 -**WebSocketConfig.groovy** -```groovy -@Configuration -@EnableWebSocket -@EnableWebSocketMessageBroker -class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { - - @Override - void configureMessageBroker(MessageBrokerRegistry config) { - config.enableSimpleBroker("/topic", "/queue", "/exchange"); -// config.enableStompBrokerRelay("/topic", "/queue", "/exchange"); // Uncomment for external message broker (ActiveMQ, RabbitMQ) - config.setApplicationDestinationPrefixes("/topic", "/queue"); // prefix in client queries - config.setUserDestinationPrefix("/user"); - } +1. 后端示例: - @Override - void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint("/example-endpoint").withSockJS() - } -} -``` +**WebSocketConfig.groovy** + + @Configuration + @EnableWebSocket + + @EnableWebSocketMessageBroker + + class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + void configureMessageBroker(MessageBrokerRegistry config) { + + long[] heartbeat = [ 30000, 30000 ]; + config.enableSimpleBroker("/topic", "/queue", "/exchange") + .setTaskScheduler(new DefaultManagedTaskScheduler()) // enable heartbeats + .setHeartbeatValue(heartbeat); // enable heartbeats + // config.enableStompBrokerRelay("/topic", "/queue", "/exchange"); // Uncomment for external message broker (ActiveMQ, RabbitMQ) + config.setApplicationDestinationPrefixes("/topic", "/queue"); // prefix in client queries + config.setUserDestinationPrefix("/user"); + } + + @Override + void registerStompEndpoints(StompEndpointRegistry registry) { + registry.addEndpoint("/example-endpoint").setAllowedOrigins("*").withSockJS() + } + + @Override + void configureWebSocketTransport(WebSocketTransportRegistration registration) { + registration.setMessageSizeLimit(8 * 1024); + } + } + + + **SocketController.groovy** -``` groovy -@Slf4j -@RestController -class SocketController { - - @MessageMapping('/hello-msg-mapping') - @SendTo('/topic/greetings') - EchoModel echoMessageMapping(String message) { - log.debug("React to hello-msg-mapping") - return new EchoModel(message.trim()) - } -} -``` - -Check out the full example server https://github.com/NaikSoftware/stomp-protocol-example-server - -## Example library usage - -**Basic usage** -``` java - - private StompClient mStompClient; - - // ... - - mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, "ws://10.0.2.2:8080/example-endpoint/websocket"); - mStompClient.connect(); - - mStompClient.topic("/topic/greetings").subscribe(topicMessage -> { - Log.d(TAG, topicMessage.getPayload()); - }); - - mStompClient.send("/topic/hello-msg-mapping", "My first STOMP message!").subscribe(); - - // ... - - mStompClient.disconnect(); -``` -See the full example https://github.com/NaikSoftware/StompProtocolAndroid/tree/master/example-client - -Method `Stomp.over` consume class for create connection as first parameter. -You must provide dependency for lib and pass class. -At now supported connection providers: -- `org.java_websocket.WebSocket.class` ('org.java-websocket:Java-WebSocket:1.3.0') -- `okhttp3.WebSocket.class` ('com.squareup.okhttp3:okhttp:3.8.0') - -You can add own connection provider. Just implement interface `ConnectionProvider`. -If you implement new provider, please create pull request :) - -**Subscribe lifecycle connection** -``` java -mStompClient.lifecycle().subscribe(lifecycleEvent -> { - switch (lifecycleEvent.getType()) { - - case OPENED: - Log.d(TAG, "Stomp connection opened"); - break; - - case ERROR: - Log.e(TAG, "Error", lifecycleEvent.getException()); - break; - - case CLOSED: - Log.d(TAG, "Stomp connection closed"); - break; - } -}); -``` -Library support just send & receive messages. ACK messages, transactions not implemented yet. + @Slf4j + @RestController + class SocketController { + + @Autowired + SocketService socketService + + @MessageMapping('/hello-msg-mapping') + @SendTo('/topic/greetings') + EchoModel echoMessageMapping(String message) { + log.debug("React to hello-msg-mapping") + return new EchoModel(message.trim()) + } + + @RequestMapping(value = '/hello-convert-and-send', method = RequestMethod.POST) + void echoConvertAndSend(@RequestParam('msg') String message) { + socketService.echoMessage(message) + } + } + +2. 示例用法: + +**基本用法** + + private StompClient mStompClient; + + // ... + + mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, "ws://" + ANDROID_EMULATOR_LOCALHOST + ":" + RestClient.SERVER_PORT + "/example-endpoint/websocket"); + mStompClient.connect(); + + mStompClient.topic("/topic/greetings") + .subscribeOn(Schedulers.io()) + .observeOn(HarmonySchedulers.mainThread()) + .subscribe(topicMessage -> { + debug("Received " + topicMessage.getPayload()); + addItem(mGson.fromJson(topicMessage.getPayload(), EchoModel.class)); + }, throwable -> { + debug("Error on subscribe topic" + throwable); + }); + + // ... + + mStompClient.disconnect(); + + + +. 订阅生命周期连接: + + lifecycleDisposable = connectionProvider.lifecycle() + .subscribe(lifecycleEvent -> { + switch (lifecycleEvent.getType()) { + case OPENED: + HiLog.error(LABEL, "Socket opened"); + break; + + case CLOSED: + HiLog.error(LABEL, "Socket closed"); + disconnect(); + break; + + case ERROR: + HiLog.error(LABEL, "Socket closed with error"); + lifecyclePublishSubject.onNext(lifecycleEvent); + break; + default: + break; + } + }); + + +#### 测试信息 + +CodeCheck代码测试无异常 + +CloudTest代码测试无异常 + +火绒安全病毒安全检测通过 + +当前版本demo功能与原组件基本无差异 + +## 版本迭代 +- 0.0.1-SNAPSHOT + +## 版权和许可信息 +he MIT License (MIT) + +Copyright (c) 2016 Nickolay Savchenko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/example-client/.gitignore b/entry/.gitignore similarity index 100% rename from example-client/.gitignore rename to entry/.gitignore diff --git a/entry/build.gradle b/entry/build.gradle new file mode 100644 index 0000000..773101e --- /dev/null +++ b/entry/build.gradle @@ -0,0 +1,32 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + + + signingConfigs { + debug { + storeFile file('E:\\code\\SOW-22\\StompProtocolOhos_master\\keyStore\\root_1.p12') + storePassword '00000020A5942DF11352A361FE91C774CCC6B843F4C14C06926EC4213EA4FE2A1245A629DB9C65BF5004AC75C7DE7ADD' + keyAlias = 'hos_platform_os' + keyPassword '000000206F4463D371D8569C8A9B5A531F89FAFAABE2DBA550CCA50E156A285B41F95CF0B422E0D44D60FF6BDF3077E7' + signAlg = 'SHA256withECDSA' + profile file('E:\\code\\SOW-22\\StompProtocolOhos_master\\keyStore\\StompProtocolAndroidDebug.p7b') + certpath file('E:\\code\\SOW-22\\StompProtocolOhos_master\\keyStore\\root.cer') + } + } + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 5 + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testCompile 'junit:junit:4.12' + implementation 'io.reactivex.rxjava2:rxjava:2.2.5' + implementation 'com.squareup.retrofit2:converter-gson:2.5.0' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0' + implementation 'com.squareup.retrofit2:retrofit:2.5.0' + compile project(path: ':lib') + testImplementation 'org.mockito:mockito-core:2.23.0' + testImplementation 'com.google.truth:truth:0.39' +} diff --git a/entry/src/main/config.json b/entry/src/main/config.json new file mode 100644 index 0000000..808bd37 --- /dev/null +++ b/entry/src/main/config.json @@ -0,0 +1,67 @@ +{ + "app": { + "bundleName": "ua.naiksoftware.stompclientexample", + "vendor": "naiksoftware", + "version": { + "code": 1, + "name": "1.0" + }, + "apiVersion": { + "compatible": 5, + "target": 5 + } + }, + "deviceConfig": { + "default": { + "network": { + "cleartextTraffic": true + } + } + }, + "module": { + "package": "ua.naiksoftware.stompclientexample", + "name": ".MyApplication", + "deviceType": [ + "phone" + ], + "reqPermissions": [ + { + "name": "ohos.permission.INTERNET" + } + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry" + }, + "abilities": [ + { + "metaData": { + "customizeData": [ + { + "name": "hwc-theme", + "value": "androidhwext:style/Theme.Emui.NoTitleBar" + } + ] + }, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "unspecified", + "name": "ua.naiksoftware.stompclientexample.MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "StompProtocolOhos_master", + "type": "page", + "launchType": "standard" + } + ] + } +} \ No newline at end of file diff --git a/example-client/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java similarity index 81% rename from example-client/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java rename to entry/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java index 1c694ac..b0f24ad 100644 --- a/example-client/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/EchoModel.java @@ -2,11 +2,17 @@ package ua.naiksoftware.stompclientexample; /** * Created by Naik on 24.02.17. + * + * @since 2021-04-27 */ public class EchoModel { private String echo; + /** + * 构造函数 + * + */ public EchoModel() { } diff --git a/example-client/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java similarity index 69% rename from example-client/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java rename to entry/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java index 19aeab5..a130505 100644 --- a/example-client/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/ExampleRepository.java @@ -1,15 +1,22 @@ package ua.naiksoftware.stompclientexample; import io.reactivex.Completable; -import io.reactivex.Flowable; import retrofit2.http.POST; import retrofit2.http.Query; /** * Created by Naik on 24.02.17. + * + * @since 2021-04-21 */ public interface ExampleRepository { - + /** + * Completable sendRestEcho + * + * @param message + * @return Completable + * + */ @POST("hello-convert-and-send") Completable sendRestEcho(@Query("msg") String message); } diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/MainAbility.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/MainAbility.java new file mode 100644 index 0000000..bbc1a2b --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/MainAbility.java @@ -0,0 +1,18 @@ +package ua.naiksoftware.stompclientexample; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ua.naiksoftware.stompclientexample.slice.MainAbilitySlice; + +/** + * MainAbility + * + * @since 2021-04-27 + */ +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/MyApplication.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/MyApplication.java new file mode 100644 index 0000000..00c107b --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/MyApplication.java @@ -0,0 +1,15 @@ +package ua.naiksoftware.stompclientexample; + +import ohos.aafwk.ability.AbilityPackage; + +/** + * MyApplication + * + * @since 2021-04-27 + */ +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/example-client/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java similarity index 46% rename from example-client/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java rename to entry/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java index 209a497..91eec3c 100644 --- a/example-client/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/RestClient.java @@ -6,36 +6,63 @@ import retrofit2.converter.gson.GsonConverterFactory; /** * Created by Naik on 24.02.17. + * + * @since 2021-04-27 */ public class RestClient { - public static final String ANDROID_EMULATOR_LOCALHOST = "10.0.2.2"; + /** + * 本机IP地址 测试用 + */ + public static final String OHOS_EMULATOR_LOCALHOST = getIp(); + /** + * 链接端口号 + */ public static final String SERVER_PORT = "8080"; private static RestClient instance; - private static final Object lock = new Object(); + private static final Object OBJECT_LOCK = new Object(); + private final ExampleRepository mExampleRepository; + + private RestClient() { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("http://" + OHOS_EMULATOR_LOCALHOST + ":" + SERVER_PORT + "/") + .addConverterFactory(GsonConverterFactory.create()) + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .build(); + mExampleRepository = retrofit.create(ExampleRepository.class); + } + /** + * getInstance + * + * @return RestClient + */ public static RestClient getInstance() { - RestClient instance = RestClient.instance; - if (instance == null) { - synchronized (lock) { - instance = RestClient.instance; - if (instance == null) { - RestClient.instance = instance = new RestClient(); + RestClient restClient = RestClient.instance; + if (restClient == null) { + synchronized (OBJECT_LOCK) { + restClient = RestClient.instance; + if (restClient == null) { + restClient = new RestClient(); + RestClient.instance = restClient; } } } return instance; } - private final ExampleRepository mExampleRepository; - - private RestClient() { - Retrofit retrofit = new Retrofit.Builder().baseUrl("http://" + ANDROID_EMULATOR_LOCALHOST + ":" + SERVER_PORT + "/") - .addConverterFactory(GsonConverterFactory.create()) - .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) - .build(); - mExampleRepository = retrofit.create(ExampleRepository.class); + /** + * getIp + * + * @return String + */ + public static String getIp() { + String ip = "192."; + String ip2 = "168."; + String ip3 = "3."; + String ip4 = "42"; + return ip + ip2 + ip3 + ip4; } public ExampleRepository getExampleRepository() { diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/SimpleAdapter.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/SimpleAdapter.java new file mode 100644 index 0000000..e0895d3 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/SimpleAdapter.java @@ -0,0 +1,77 @@ +package ua.naiksoftware.stompclientexample; + +import ohos.agp.components.BaseItemProvider; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.app.Context; + +import java.util.Collections; +import java.util.List; + +/** + * Created by Naik on 24.02.17 + * + * @since 2021-04-27 + */ +public class SimpleAdapter extends BaseItemProvider { + private List data; + private Context mContext; + + + /** + * 构造函数 + * * + * + * @param list + * @param context + */ + public SimpleAdapter(List list, Context context) { + this.data = list; + this.mContext = context; + } + + @Override + public int getCount() { + return data == null ? 0 : data.size(); + } + + @Override + public Object getItem(int position) { + if (data != null && position >= 0 && position < data.size()) { + return data.get(position); + } + return Collections.emptyList(); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public Component getComponent(int position, Component convertComponent, ComponentContainer componentContainer) { + ViewHolder holder = new ViewHolder(); + if (convertComponent == null) { + convertComponent = LayoutScatter.getInstance(mContext).parse(ResourceTable.Layout_item_layout, null, true); + if (convertComponent != null) { + holder.title = (Text) convertComponent.findComponentById(ResourceTable.Id_text); + convertComponent.setTag(holder); + } + } else { + holder = (ViewHolder) convertComponent.getTag(); + } + holder.title.setText(data.get(position)); + return convertComponent; + } + + /** + * ViewHolder + * + * @since 2021-04-27 + */ + private static class ViewHolder { + Text title; + } +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/BaseDirectionalLayout.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/BaseDirectionalLayout.java new file mode 100644 index 0000000..a17ba7b --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/BaseDirectionalLayout.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ua.naiksoftware.stompclientexample.layout; + +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.element.ShapeElement; +import ohos.app.Context; +import ohos.multimodalinput.event.MmiPoint; +import ohos.multimodalinput.event.TouchEvent; + +/** + * 自定义线性布局,实现点击背景变成深色的效果 + * + * @since 2021-04-19 + */ +public class BaseDirectionalLayout extends ohos.agp.components.DirectionalLayout + implements Component.TouchEventListener, Component.ClickedListener, Component.LongClickedListener { + private ShapeElement mGrayShapeElement = new ShapeElement(); + private ShapeElement mWhiteShapeElement = new ShapeElement(); + private float mTouchCenterX; + private float mTouchCenterY; + private float oldContentY = 0; + private float oldContentX = 0; + private float distanceUp = 0; + private boolean isLongClick = false; + private boolean isEnable = true; + private boolean isNeedBack = false; + + /** + * BaseDirectionalLayout的构造方法,在Java类中new时调用 + * + * @param context + */ + public BaseDirectionalLayout(Context context) { + super(context); + initShapeElement(); + } + + /** + * BaseDirectionalLayout的构造方法,在xml布局中 + * + * @param context + * @param attrSet + */ + public BaseDirectionalLayout(Context context, AttrSet attrSet) { + super(context, attrSet); + initShapeElement(); + } + + /** + * BaseDirectionalLayout的构造方法,在xml布局且加Style时调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BaseDirectionalLayout(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + initShapeElement(); + } + + /** + * setEnable + * + * @param isEnable isEnable + */ + public void setEnable(boolean isEnable) { + this.isEnable = isEnable; + } + + /** + * setNeedBack + * + * @param isBack isBack + */ + public void setNeedBack(boolean isBack) { + this.isNeedBack = isBack; + } + + private void initShapeElement() { + setLongClickedListener(this::onLongClicked); + setClickedListener(this::onClick); + setTouchEventListener(this::onTouchEvent); + mGrayShapeElement.setRgbColor(new RgbColor(FinalStaticBean.NUM_120, + FinalStaticBean.NUM_126, + FinalStaticBean.NUM_130)); + mWhiteShapeElement.setRgbColor(new RgbColor(FinalStaticBean.NUM_255, + FinalStaticBean.NUM_255, + FinalStaticBean.NUM_255)); + } + + @Override + public void onClick(Component component) { + + } + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + int action = touchEvent.getAction(); + MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex()); + switch (action) { + case TouchEvent.PRIMARY_POINT_DOWN: + setBackground(mGrayShapeElement); + setAlpha(FinalStaticBean.NUM_HALF); + mTouchCenterX = point.getX(); + mTouchCenterY = point.getY(); + oldContentX = getContentPositionX(); + oldContentY = getContentPositionY(); + break; + case TouchEvent.POINT_MOVE: + setBackground(mWhiteShapeElement); + setAlpha(1); + break; + case TouchEvent.PRIMARY_POINT_UP: + if (isNeedBack && isEnable) { + setContentPosition(oldContentX, oldContentY); + } + setBackground(mWhiteShapeElement); + setAlpha(1); + isLongClick = false; + break; + case TouchEvent.CANCEL: + setBackground(mWhiteShapeElement); + setAlpha(1); + break; + default: + break; + } + return true; + } + + + @Override + public void onLongClicked(Component component) { + isLongClick = true; + + } +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/FinalStaticBean.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/FinalStaticBean.java new file mode 100644 index 0000000..ac47c34 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/FinalStaticBean.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ua.naiksoftware.stompclientexample.layout; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +/** + * FinalStaticBean 常数标志类 + * + * @since 2021-03-27 + */ +public abstract class FinalStaticBean { + /** + * 表示横向网格布局 + */ + public static final int GRIDLAYOUTHORIZONTALTYPE = 1; + /** + * 表示纵向网格布局 + */ + public static final int GRIDLAYOUTVERTICALTYPE = 2; + /** + * 表示列表布局 + */ + public static final int LINEARLAYOUTTYPE = 3; + /** + * 统一HiLogLabel + */ + public static final HiLogLabel DRAGLISTVIEW = new HiLogLabel(HiLog.LOG_APP, 0x00201, "DragListView"); + /** + * 表示弧度边框 + */ + public static final int RANDIUBORDER = 0; + /** + * 无边框 + */ + public static final int NOBORDER = 1; + /** + * 添加布局 + */ + public static final int ADDCOLUMN = 200; + /** + * 删除布局 + */ + public static final int REMOVECOLUMN = 410; + /** + * 横向列表布局 + */ + public static final int HORIZONTALLISTLAYOUT = 12; + /** + * 横向网格布局 + */ + public static final int HORIZONTALGRIDLAYOUT = 18; + /** + * 清除所有item + */ + public static final int CLEARBOARD = 1019; + /** + * 横向滑动布局的宽度为屏幕的0.85 + */ + public static final double DISPLAYWIDTH = 0.85; + /** + * 左滑标志 + */ + public static final int LEFTMOVE = 4; + /** + * 右滑标志 + */ + public static final int RIGHTMOVE = 5; + /** + * 允许滑动标志 + */ + public static final int ENABLEDRAG = 6; + /** + * 禁止滑动标志 + */ + public static final int DISABLEDRAG = 7; + /** + * 上滑标志 + */ + public static final int UPMOVE = 8; + /** + * 下滑标志 + */ + public static final int DOWNMOVE = 8; + /** + * 代替常数0 + */ + public static final int NUM_0 = 0; + /** + * 代替常数1 + */ + public static final int NUM_1 = 1; + /** + * 代替常数2 + */ + public static final int NUM_2 = 2; + /** + * 代替常数3 + */ + public static final int NUM_3 = 3; + /** + * 代替常数4 + */ + public static final int NUM_4 = 4; + /** + * 代替常数5 + */ + public static final int NUM_5 = 5; + /** + * 代替常数7 + */ + public static final int NUM_7 = 7; + /** + * 代替常数12 + */ + public static final int NUM_12 = 12; + /** + * 代替常数15 + */ + public static final int NUM_15 = 15; + /** + * 代替常数16 + */ + public static final int NUM_16 = 16; + /** + * 代替常数20 + */ + public static final int NUM_20 = 20; + /** + * 代替常数40 + */ + public static final int NUM_40 = 40; + /** + * 代替常数50 + */ + public static final int NUM_50 = 50; + /** + * 代替常数58 + */ + public static final int NUM_58 = 58; + /** + * 代替常数100 + */ + public static final int NUM_100 = 100; + /** + * 代替常数120 + */ + public static final int NUM_120 = 120; + /** + * 代替常数120 + */ + public static final int NUM_126 = 126; + /** + * 代替常数120 + */ + public static final int NUM_130 = 130; + /** + * 代替常数150 + */ + public static final int NUM_150 = 150; + /** + * 代替常数198 + */ + public static final int NUM_198 = 198; + /** + * 代替常数200 + */ + public static final int NUM_200 = 200; + /** + * 代替常数255 + */ + public static final int NUM_255 = 255; + /** + * 代替常数400 + */ + public static final int NUM_400 = 400; + /** + * 代替常数500 + */ + public static final int NUM_500 = 500; + /** + * 代替常数840 + */ + public static final int NUM_840 = 840; + /** + * 代替常数1000 + */ + public static final int NUM_1000 = 1000; + /** + * 代替常数1800 + */ + public static final int NUM_1800 = 1800; + /** + * 代替常数1400 + */ + public static final int NUM_4000 = 4000; + /** + * 代替常数5000 + */ + public static final int NUM_5000 = 5000; + /** + * 代替常数0.5f + */ + public static final float NUM_HALF = 0.5f; + /** + * 代替常数0.8f + */ + public static final float NUM_ZERO_EIGHT = 0.8f; + /** + * 代替常数0.9f + */ + public static final float NUM_ZERO_NINE = 0.9f; + /** + * 代替常数1f + */ + public static final float NUM_ONE_FLOAT = 1f; + /** + * 代替字符串0 + */ + public static final String ZERO_STRING = "0"; + /** + * 代替字符串Item + */ + public static final String ITEM = "Item "; + /** + * 代替字符串Test + */ + public static final String TEST = "Test "; + /** + * 代替字符串Test board + */ + public static final String TEST_LIST = "Test lists"; + /** + * 代替字符串Disable drag + */ + public static final String DISABLEDRAG_STRING = "Disable drag"; + /** + * 代替字符串Grid layout + */ + public static final String GRIDLAYOUT = "Grid layout"; + /** + * 代替字符串Add column + */ + public static final String ADDCOLUMN_STRING = "Add column"; + /** + * 代替字符串Remove column + */ + public static final String REMOVECOLUMN_STRING = "Remove column"; + /** + * 代替字符串Clear board + */ + public static final String CLEARBOARD_STRING = "Clear board"; + /** + * Rgb中灰色值 + */ + public static final int GRAY = 198; + /** + * Rgb中白色值 + */ + public static final int WHITE = 255; +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/ToastUtil.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/ToastUtil.java new file mode 100644 index 0000000..fe1ecee --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/layout/ToastUtil.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ua.naiksoftware.stompclientexample.layout; + +import ohos.agp.components.*; +import ohos.agp.utils.LayoutAlignment; +import ohos.agp.window.dialog.ToastDialog; +import ohos.app.Context; + +/** + * toast工具类,可快速实现toast效果,支持设置圆角弧度,x,y轴偏移和权重方式 + * + * @since 2021-04-19 + */ +public class ToastUtil { + private static int radius = FinalStaticBean.NUM_58; + private Context context; + + /** + * Toast构造器 + * + * @param context + */ + public ToastUtil(Context context) { + this.context = context; + } + + /** + * 支持静态方法,传入上下文和需要显示的文字 + * + * @param ctx ctx + * @param text text + */ + public static void toastCtx(Context ctx, String text) { + new ToastDialog(ctx) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAutoClosable(true) + .setDuration(FinalStaticBean.NUM_5000) + .setCornerRadius(radius) + .show(); + } + + /** + * 支持静态方法,传入上下文和需要布局 + * + * @param ctx ctx + * @param layout layout + */ + public static void toastCtx(Context ctx, Component layout) { + Component customToastLayout = (Component) LayoutScatter.getInstance(ctx).parse(layout.getId(), null, false); + ToastDialog toastDialog = new ToastDialog(ctx); + toastDialog.setComponent(customToastLayout); + toastDialog.setCornerRadius(radius); + toastDialog.setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT); + toastDialog.setAlignment(LayoutAlignment.CENTER); + toastDialog.show(); + } + + /** + * 支持静态方法,传入需要显示的文字 + * + * @param text text + */ + public void toast(String text) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAutoClosable(true) + .setDuration(FinalStaticBean.NUM_5000) + .setCornerRadius(radius) + .show(); + } + + /** + * 支持静态方法,传入需要显示的文字和圆角角度 + * + * @param text text + * @param duration duration + */ + public void toast(String text, int duration) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setDuration(duration) + .setCornerRadius(radius) + .show(); + } + + /** + * 支持静态方法,传入需要显示的文字,圆角,X轴偏移,Y轴偏移,权重 + * + * @param text text + * @param duration duration + * @param offsetX offsetX + * @param offsetY offsetY + * @param gravity gravity + */ + public void toast(String text, int duration, int offsetX, int offsetY, int gravity) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAlignment(gravity) + .setDuration(duration) + .setCornerRadius(radius) + .setOffset(offsetX, offsetY) + .show(); + } +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHandlerScheduler.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHandlerScheduler.java new file mode 100644 index 0000000..22b7918 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHandlerScheduler.java @@ -0,0 +1,130 @@ +package ua.naiksoftware.stompclientexample.rxHarmony; + +import io.reactivex.Scheduler; +import io.reactivex.disposables.Disposable; +import io.reactivex.disposables.Disposables; +import io.reactivex.plugins.RxJavaPlugins; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.InnerEvent; + +import java.util.concurrent.TimeUnit; + +/** + * HandlerScheduler + * + * @since 2021-04-27 + */ +final class OpenHandlerScheduler extends Scheduler { + + private static final int INNER_EVENT_ID = 9819; + private final EventHandler handler; + + /** + * HandlerWorker + * + * @since 2021-04-27 + */ + private static final class HandlerWorker extends Worker { + private final EventHandler handler; + private volatile boolean isDisposed; + + HandlerWorker(EventHandler handler) { + this.handler = handler; + } + + @Override + public Disposable schedule(Runnable run, long delay, TimeUnit unit) { + if (run == null) { + throw new NullPointerException("run == null"); + } + if (unit == null) { + throw new NullPointerException("unit == null"); + } + + if (isDisposed) { + return Disposables.disposed(); + } + ScheduledRunnable scheduled = new ScheduledRunnable(handler, RxJavaPlugins.onSchedule(run)); + + InnerEvent event1 = InnerEvent.get(INNER_EVENT_ID, 0, null); + + handler.postTask(scheduled, unit.toMillis(delay)); + + /** + * Re-check disposed state for removing in case we were racing a call to dispose(). + */ + if (isDisposed) { + handler.removeAllEvent(); + return Disposables.disposed(); + } + + return scheduled; + } + + @Override + public void dispose() { + isDisposed = true; + handler.removeAllEvent(); + } + + @Override + public boolean isDisposed() { + return isDisposed; + } + } + + /** + * ScheduledRunnable + * + * @since 2021-04-27 + */ + private static final class ScheduledRunnable implements Runnable, Disposable { + private final EventHandler handler; + private final Runnable delegate; + + private volatile boolean isDisposed; + + ScheduledRunnable(EventHandler handler, Runnable delegate) { + this.handler = handler; + this.delegate = delegate; + } + + @Override + public void run() { + delegate.run(); + } + + @Override + public void dispose() { + isDisposed = true; + handler.removeAllEvent(); + } + + @Override + public boolean isDisposed() { + return isDisposed; + } + } + + OpenHandlerScheduler(EventHandler handler) { + this.handler = handler; + } + + @Override + public Disposable scheduleDirect(Runnable run, long delay, TimeUnit unit) { + if (run == null) { + throw new NullPointerException("run == null"); + } + if (unit == null) { + throw new NullPointerException("unit == null"); + } + ScheduledRunnable scheduled = new ScheduledRunnable(handler, RxJavaPlugins.onSchedule(run)); + handler.postTask(scheduled, unit.toMillis(delay)); + return scheduled; + } + + @Override + public Worker createWorker() { + return new HandlerWorker(handler); + } +} diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHarmonySchedulers.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHarmonySchedulers.java new file mode 100644 index 0000000..3796397 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/OpenHarmonySchedulers.java @@ -0,0 +1,63 @@ +package ua.naiksoftware.stompclientexample.rxHarmony; + +import io.reactivex.Scheduler; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + + + +/** + * HmOs-specific Schedulers. + * + * @since 2021-04-27 + */ +public final class OpenHarmonySchedulers { + private static final HiLogLabel LABEL = new HiLogLabel(0, 0, "HarmonySchedulers"); + + /** + * MainHolder + * + * @since 2021-03-29 + */ + private static final class MainHolder { + static final Scheduler DEFAULT = new OpenHandlerScheduler(new EventHandler(EventRunner.getMainEventRunner())); + } + + private static final Scheduler MAIN_THREAD = RxHmOSPlugins.initMainThreadScheduler( + () -> MainHolder.DEFAULT); + + /** + * 构造函数 + */ + private OpenHarmonySchedulers() { + throw new AssertionError("No instances."); + } + + /** + * 主线程 + * * + * + * @return Scheduler + */ + public static Scheduler mainThread() { + return RxHmOSPlugins.onMainThreadScheduler(MAIN_THREAD); + } + + /** + * from 根据 eventRunner 返回 Scheduler + * + * @param eventRunner + * @return + */ + public static Scheduler from(EventRunner eventRunner) { + if (eventRunner == null) { + HiLog.debug(LABEL,"eventRunner == null"); + return null; + } else { + return new OpenHandlerScheduler(new EventHandler(eventRunner)); + } + } +} + diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/RxHmOSPlugins.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/RxHmOSPlugins.java new file mode 100644 index 0000000..d99a248 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/rxHarmony/RxHmOSPlugins.java @@ -0,0 +1,111 @@ +package ua.naiksoftware.stompclientexample.rxHarmony; + +import io.reactivex.Scheduler; +import io.reactivex.exceptions.Exceptions; +import io.reactivex.functions.Function; + +import java.util.concurrent.Callable; + +public class RxHmOSPlugins { + + private static volatile Function, Scheduler> onInitMainThreadHandler; + private static volatile Function onMainThreadHandler; + private RxHmOSPlugins() { + throw new AssertionError("No instances."); + } + public static void setInitMainThreadSchedulerHandler(Function, Scheduler> handler) { + onInitMainThreadHandler = handler; + } + + /** + * 创建线程 + * + * @param scheduler + * @return + */ + public static Scheduler initMainThreadScheduler(Callable scheduler) { + if (scheduler == null) { + throw new NullPointerException("scheduler == null"); + } + Function, Scheduler> f = onInitMainThreadHandler; + if (f == null) { + return callRequireNonNull(scheduler); + } + return applyRequireNonNull(f, scheduler); + } + + public static void setMainThreadSchedulerHandler(Function handler) { + onMainThreadHandler = handler; + } + + /** + * onMainThreadScheduler + * + * @param scheduler + * @return Scheduler + */ + public static Scheduler onMainThreadScheduler(Scheduler scheduler) { + if (scheduler == null) { + throw new NullPointerException("scheduler == null"); + } + Function f = onMainThreadHandler; + if (f == null) { + return scheduler; + } + return apply(f, scheduler); + } + + /** + * Returns the current hook function. + * @return the hook function, may be null + */ + public static Function, Scheduler> getInitMainThreadSchedulerHandler() { + return onInitMainThreadHandler; + } + + /** + * Returns the current hook function. + * @return the hook function, may be null + */ + public static Function getOnMainThreadSchedulerHandler() { + return onMainThreadHandler; + } + + /** + * Removes all handlers and resets the default behavior. + */ + public static void reset() { + setInitMainThreadSchedulerHandler(null); + setMainThreadSchedulerHandler(null); + } + + static Scheduler callRequireNonNull(Callable s) { + try { + Scheduler scheduler = s.call(); + if (scheduler == null) { + throw new NullPointerException("Scheduler Callable returned null"); + } + return scheduler; + } catch (Throwable ex) { + throw Exceptions.propagate(ex); + } + } + + static Scheduler applyRequireNonNull(Function, Scheduler> f, Callable s) { + Scheduler scheduler = apply(f,s); + if (scheduler == null) { + throw new NullPointerException("Scheduler Callable returned null"); + } + return scheduler; + } + + static R apply(Function f, T t) { + try { + return f.apply(t); + } catch (Throwable ex) { + throw Exceptions.propagate(ex); + } + } + + +} diff --git a/example-client/src/main/java/ua/naiksoftware/stompclientexample/MainActivity.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/slice/MainAbilitySlice.java similarity index 39% rename from example-client/src/main/java/ua/naiksoftware/stompclientexample/MainActivity.java rename to entry/src/main/java/ua/naiksoftware/stompclientexample/slice/MainAbilitySlice.java index fd35cde..f319bea 100644 --- a/example-client/src/main/java/ua/naiksoftware/stompclientexample/MainActivity.java +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/slice/MainAbilitySlice.java @@ -1,92 +1,162 @@ -package ua.naiksoftware.stompclientexample; +package ua.naiksoftware.stompclientexample.slice; -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.widget.Toast; +import static ua.naiksoftware.stompclientexample.RestClient.OHOS_EMULATOR_LOCALHOST; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -import androidx.appcompat.app.AppCompatActivity; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import io.reactivex.CompletableTransformer; -import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Button; +import ohos.agp.components.Component; +import ohos.agp.components.ListContainer; +import ohos.agp.components.Text; +import ohos.agp.text.Font; +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; import ua.naiksoftware.stomp.Stomp; -import ua.naiksoftware.stomp.dto.StompHeader; import ua.naiksoftware.stomp.StompClient; +import ua.naiksoftware.stomp.dto.StompHeader; +import ua.naiksoftware.stompclientexample.EchoModel; +import ua.naiksoftware.stompclientexample.ResourceTable; +import ua.naiksoftware.stompclientexample.RestClient; +import ua.naiksoftware.stompclientexample.SimpleAdapter; +import ua.naiksoftware.stompclientexample.rxHarmony.OpenHarmonySchedulers; +import ua.naiksoftware.stompclientexample.utils.ToastUtil; -import static ua.naiksoftware.stompclientexample.RestClient.ANDROID_EMULATOR_LOCALHOST; - -public class MainActivity extends AppCompatActivity { - - private static final String TAG = "MainActivity"; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +/** + * MainAbilitySlice + * + * @since 2021-04-27 + */ +public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener { + static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "MainAbilitySlice"); + private static final int NUM_1000 = 1000; + private static final String LOGIN = "login"; + private static final String PASSCODE = "passcode"; private SimpleAdapter mAdapter; private List mDataSet = new ArrayList<>(); private StompClient mStompClient; private Disposable mRestPingDisposable; private final SimpleDateFormat mTimeFormat = new SimpleDateFormat("HH:mm:ss", Locale.getDefault()); - private RecyclerView mRecyclerView; + private Text text; + private ListContainer mRecyclerView; + private Button mBtConnectStomp; + private Button mBtDisconnetStomp; + private Button mBtEchotStomp; + private Button mBtEchoRest; private Gson mGson = new GsonBuilder().create(); - private CompositeDisposable compositeDisposable; @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - mRecyclerView = findViewById(R.id.recycler_view); - mAdapter = new SimpleAdapter(mDataSet); - mAdapter.setHasStableIds(true); - mRecyclerView.setAdapter(mAdapter); - mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, true)); - - mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, "ws://" + ANDROID_EMULATOR_LOCALHOST + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_main); + mRecyclerView = (ListContainer) findComponentById(ResourceTable.Id_recycler_view); + mBtConnectStomp = (Button) findComponentById(ResourceTable.Id_bt_connect_stomp); + mBtDisconnetStomp = (Button) findComponentById(ResourceTable.Id_bt_disconnect_stomp); + mBtEchotStomp = (Button) findComponentById(ResourceTable.Id_bt_echo_stomp); + mBtEchoRest = (Button) findComponentById(ResourceTable.Id_bt_echo_rest); + text = (Text) findComponentById(ResourceTable.Id_tv_title); + mBtConnectStomp.setClickedListener(this); + mBtDisconnetStomp.setClickedListener(this); + mBtEchotStomp.setClickedListener(this); + mBtEchoRest.setClickedListener(this); + mBtConnectStomp.setFont(Font.DEFAULT_BOLD); + mBtDisconnetStomp.setFont(Font.DEFAULT_BOLD); + mBtEchotStomp.setFont(Font.DEFAULT_BOLD); + mBtEchoRest.setFont(Font.DEFAULT_BOLD); + mAdapter = new SimpleAdapter(mDataSet, getContext()); + mRecyclerView.setItemProvider(mAdapter); + mStompClient = Stomp.over(Stomp.ConnectionProvider.OKHTTP, "ws://" + OHOS_EMULATOR_LOCALHOST + ":" + RestClient.SERVER_PORT + "/example-endpoint/websocket"); - resetSubscriptions(); + text.setFont(Font.DEFAULT_BOLD); } - public void disconnectStomp(View view) { - mStompClient.disconnect(); + private void resetSubscriptions() { + if (compositeDisposable != null) { + compositeDisposable.dispose(); + } + compositeDisposable = new CompositeDisposable(); + } + + @Override + public void onClick(Component component) { + switch (component.getId()) { + case ResourceTable.Id_bt_connect_stomp: + connectStomp(); + break; + case ResourceTable.Id_bt_disconnect_stomp: + disconnectStomp(); + break; + case ResourceTable.Id_bt_echo_stomp: + sendEchoViaStomp(); + break; + case ResourceTable.Id_bt_echo_rest: + sendEchoViaRest(); + break; + default: + break; + } } - public static final String LOGIN = "login"; + @Override + public void onActive() { + super.onActive(); + } - public static final String PASSCODE = "passcode"; + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } - public void connectStomp(View view) { + /** + * 断开连接 + */ + public void disconnectStomp() { + boolean disconnect = mStompClient.disconnect(); + if (disconnect) { + toast("Stomp connection closed"); + } + } + + /** + * 启动链接 + */ + public void connectStomp() { List headers = new ArrayList<>(); headers.add(new StompHeader(LOGIN, "guest")); headers.add(new StompHeader(PASSCODE, "guest")); - mStompClient.withClientHeartbeat(1000).withServerHeartbeat(1000); + mStompClient.withClientHeartbeat(NUM_1000).withServerHeartbeat(NUM_1000); resetSubscriptions(); + debug("connectStomp"); + Disposable dispLifecycle = mStompClient.lifecycle() .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) + .observeOn(OpenHarmonySchedulers.mainThread()) .subscribe(lifecycleEvent -> { switch (lifecycleEvent.getType()) { case OPENED: toast("Stomp connection opened"); break; case ERROR: - Log.e(TAG, "Stomp connection error", lifecycleEvent.getException()); - toast("Stomp connection error"); + debug("Stomp connection error"); + toast("Stomp connection error"); break; case CLOSED: toast("Stomp connection closed"); @@ -95,6 +165,8 @@ public class MainActivity extends AppCompatActivity { case FAILED_SERVER_HEARTBEAT: toast("Stomp failed server heartbeat"); break; + default: + break; } }); @@ -103,74 +175,112 @@ public class MainActivity extends AppCompatActivity { // Receive greetings Disposable dispTopic = mStompClient.topic("/topic/greetings") .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) + .observeOn(OpenHarmonySchedulers.mainThread()) .subscribe(topicMessage -> { - Log.d(TAG, "Received " + topicMessage.getPayload()); + debug("Received " + topicMessage.getPayload()); addItem(mGson.fromJson(topicMessage.getPayload(), EchoModel.class)); + notifyList(mDataSet.size() - 1); }, throwable -> { - Log.e(TAG, "Error on subscribe topic", throwable); + debug("Error on subscribe topic" + throwable); }); compositeDisposable.add(dispTopic); mStompClient.connect(headers); + + debug("connectStomp end "); + } - public void sendEchoViaStomp(View v) { -// if (!mStompClient.isConnected()) return; - compositeDisposable.add(mStompClient.send("/topic/hello-msg-mapping", "Echo STOMP " + mTimeFormat.format(new Date())) + /** + * 发送消息 + */ + public void sendEchoViaStomp() { + compositeDisposable.add(mStompClient.send("/topic/hello-msg-mapping", + "Echo STOMP " + mTimeFormat.format(new Date())) .compose(applySchedulers()) .subscribe(() -> { - Log.d(TAG, "STOMP echo send successfully"); + notifyList(mDataSet.size()); + debug("STOMP echo send successfully"); }, throwable -> { - Log.e(TAG, "Error send STOMP echo", throwable); - toast(throwable.getMessage()); + debug("Error send STOMP echo" + throwable); + toast(throwable.getMessage() + "Message Connect ERROR"); })); } - public void sendEchoViaRest(View v) { + + /** + * 重连 + */ + public void sendEchoViaRest() { mRestPingDisposable = RestClient.getInstance().getExampleRepository() .sendRestEcho("Echo REST " + mTimeFormat.format(new Date())) .compose(applySchedulers()) .subscribe(() -> { - Log.d(TAG, "REST echo send successfully"); + + debug("REST echo send successfully"); }, throwable -> { - Log.e(TAG, "Error send REST echo", throwable); + debug("Error send REST echo" + throwable); toast(throwable.getMessage()); }); } + /** + * addItem + * + * @param echoModel echoModel + */ private void addItem(EchoModel echoModel) { mDataSet.add(echoModel.getEcho() + " - " + mTimeFormat.format(new Date())); - mAdapter.notifyDataSetChanged(); - mRecyclerView.smoothScrollToPosition(mDataSet.size() - 1); + notifyList(mDataSet.size()); + } + + private void notifyList(int pos) { + mRecyclerView.scrollTo(pos); + mAdapter.notifyDataChanged(); } - private void toast(String text) { - Log.i(TAG, text); - Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); + /** + * toast + * + * @param string string + */ + private void toast(String string) { + debug(string); + ToastUtil.toast(this, string); } + /** + * applySchedulers + * + * @return CompletableTransformer + */ protected CompletableTransformer applySchedulers() { + return upstream -> upstream .unsubscribeOn(Schedulers.newThread()) .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()); + .observeOn(OpenHarmonySchedulers.mainThread()); } - private void resetSubscriptions() { + @Override + protected void onStop() { + mStompClient.disconnect(); + if (mRestPingDisposable != null) { + mRestPingDisposable.dispose(); + } if (compositeDisposable != null) { compositeDisposable.dispose(); } - compositeDisposable = new CompositeDisposable(); + super.onStop(); } - @Override - protected void onDestroy() { - mStompClient.disconnect(); - - if (mRestPingDisposable != null) mRestPingDisposable.dispose(); - if (compositeDisposable != null) compositeDisposable.dispose(); - super.onDestroy(); + /** + * debug + * + * @param msg + */ + private void debug(String msg) { + HiLog.error(LABEL, msg, 0); } } diff --git a/entry/src/main/java/ua/naiksoftware/stompclientexample/utils/ToastUtil.java b/entry/src/main/java/ua/naiksoftware/stompclientexample/utils/ToastUtil.java new file mode 100644 index 0000000..01bf105 --- /dev/null +++ b/entry/src/main/java/ua/naiksoftware/stompclientexample/utils/ToastUtil.java @@ -0,0 +1,134 @@ +package ua.naiksoftware.stompclientexample.utils; + +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.DirectionalLayout; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.agp.utils.LayoutAlignment; +import ohos.agp.window.dialog.ToastDialog; +import ohos.app.Context; +import ua.naiksoftware.stompclientexample.ResourceTable; + +/** + * ToastUtil + * + * @since 2021-03-29 + */ +public class ToastUtil { + private static final int NUM_5000 = 5000; + private static final int NUM_58 = 58; + Context context; + + /** + * 构造 ToastUtil + * + * @param context + */ + public ToastUtil(Context context) { + this.context = context; + } + + /** + * toastCtx + * + * @param ctx + * @param text + */ + public static void toastCtx(Context ctx, String text) { + new ToastDialog(ctx) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAutoClosable(true) + .setDuration(NUM_5000) + .setCornerRadius(NUM_58) + .show(); + } + + /** + * toastCtx + * + * @param ctx + * @param layout + */ + public static void toastCtx(Context ctx, Component layout) { + Component customToastLayout = (Component) LayoutScatter.getInstance(ctx).parse(layout.getId(), null, false); + ToastDialog toastDialog = new ToastDialog(ctx); + toastDialog.setComponent(customToastLayout); + toastDialog.setCornerRadius(NUM_58); + toastDialog.setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT); + toastDialog.setAlignment(LayoutAlignment.CENTER); + toastDialog.show(); + } + + /** + * toast + * + * @param text + */ + public void toast(String text) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAutoClosable(true) + .setDuration(NUM_5000) + .setCornerRadius(NUM_58) + .show(); + } + + /** + * toast + * + * @param text + * @param duration + */ + public void toast(String text, int duration) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setDuration(duration) + .setCornerRadius(NUM_58) + .show(); + } + + /** + * toast + * + * @param text + * @param duration + * @param offsetX + * @param offsetY + * @param gravity + */ + public void toast(String text, int duration, int offsetX, int offsetY, int gravity) { + new ToastDialog(context) + .setText(text) + .setSize(ComponentContainer.LayoutConfig.MATCH_PARENT, + ComponentContainer.LayoutConfig.MATCH_CONTENT) + .setAlignment(gravity) + .setDuration(duration) + .setCornerRadius(NUM_58) + .setOffset(offsetX, offsetY) + .show(); + } + + /** + * void + * + * @param context + * @param text + */ + public static void toast(Context context, String text) { + ComponentContainer customToastLayout = (ComponentContainer) LayoutScatter.getInstance(context) + .parse(ResourceTable.Layout_toast_dialog_layout, null, false); + Text textView = (Text) customToastLayout.findComponentById(ResourceTable.Id_toast_text); + textView.setText(text); + ToastDialog toastDialog = new ToastDialog(context); + toastDialog.setComponent(customToastLayout); + toastDialog.setCornerRadius(NUM_58); + toastDialog.setSize(ComponentContainer.LayoutConfig.MATCH_CONTENT, + DirectionalLayout.LayoutConfig.MATCH_CONTENT); + toastDialog.setAlignment(LayoutAlignment.BOTTOM); + toastDialog.show(); + } +} diff --git a/entry/src/main/resources/base/element/color.json b/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000..73ff154 --- /dev/null +++ b/entry/src/main/resources/base/element/color.json @@ -0,0 +1,185 @@ +{ + "color": [ + { + "name": "ic_advertise", + "value": "#FFFFFF" + }, + { + "name": "colorAccent", + "value": "#FF4081" + }, + { + "name": "colorCg", + "value": "#d3d7d4" + }, + { + "name": "layer_grid_line", + "value": "#000000" + }, + { + "name": "app_mainclolr", + "value": "#FB6A8F" + },{ + "name": "app_qing2", + "value": "#31C453" + },{ + "name": "color_1", + "value": "#AAA3DB" + },{ + "name": "color_2", + "value": "#86ACE9" + },{ + "name": "color_4", + "value": "#80D8A3" + },{ + "name": "color_5", + "value": "#F1C672" + },{ + "name": "color_6", + "value": "#FDAD8B" + },{ + "name": "color_7", + "value": "#ADBEFF" + },{ + "name": "color_8", + "value": "#94D6FA" + },{ + "name": "color_9", + "value": "#C3B5F6" + },{ + "name": "color_10", + "value": "#99CCFF" + },{ + "name": "color_11", + "value": "#FBA6ED" + },{ + "name": "color_30", + "value": "#EE8262" + },{ + "name": "bg_color", + "value":"#F0F0F0" + },{ + "name": "color_31", + "value": "#EE6363" + },{ + "name": "color_32", + "value": "#EEB4B4" + },{ + "name": "color_33", + "value": "#D2B48C" + },{ + "name": "color_34", + "value": "#CD9B9B" + },{ + "name": "color_35", + "value": "#5F9EA0" + }, + { + "name": "app_course_chooseweek_bg", + "value": "#E2F7F6" + }, + { + "name": "app_white", + "value": "#ffffff" + }, + { + "name": "app_course_chooseweek_bg2", + "value": "#F1FFFE" + }, + { + "name":"test", + "value":"#3FCAB8" + }, + { + "name":"app_red", + "value":"#d81e06" + }, + { + "name":"color_3", + "value":"#92D261" + }, + { + "name":"app_white_slight", + "value":"#FBFBFB" + }, + { + "name":"app_course_textcolor_blue", + "value":"#13B0F1" + }, + { + "name":"app_gray", + "value":"#999999" + }, + { + "name":"app_gold", + "value":"#FF7A59" + },{ + "name": "colorPrimary", + "value": "#E6000000" + }, + { + "name": "colorSecondary", + "value": "#99000000" + }, + { + "name": "colorAppbarTitle", + "value": "#000000" + }, + { + "name": "colorAppbarBg", + "value": "#ffffff" + }, + { + "name": "colorAppbarSubBg", + "value": "#ffffff" + }, + { + "name": "textColorPrimary", + "value": "#E6000000" + }, + { + "name": "textColorSecondary", + "value": "#99000000" + }, + { + "name": "colorCardViewBg", + "value": "#ffffff" + }, + { + "name": "colorAppBackground", + "value": "#f1f3f5" + }, + { + "name": "colorSearchBarBackground", + "value": "#0C000000" + }, + { + "name": "colorListDivider", + "value": "#33000000" + }, + { + "name": "colorListHeadBackground", + "value": "#77787b" + }, + { + "name": "white", + "value": "#ffffff" + }, + { + "name": "colorPrimaryDark", + "value": "#303F9F" + }, + { + "name": "black", + "value": "#000000" + }, + { + "name": "green", + "value": "#45b97c" + }, + { + "name": "brown", + "value": "#843900" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000..710b5d3 --- /dev/null +++ b/entry/src/main/resources/base/element/string.json @@ -0,0 +1,28 @@ +{ + "string": [ + { + "name": "app_name", + "value": "StompProtocolOhos_master" + }, + { + "name": "mainability_description", + "value": "Java_Phone_Empty Feature Ability" + }, + { + "name": "send_mode_1", + "value": "ECHO STOMP" + }, + { + "name": "send_mode_2", + "value": "ECHO REST" + }, + { + "name": "connect_stomp", + "value": "CONNECT STOMP" + }, + { + "name": "disconnect_stomp", + "value": "DISCONNECT STOMP" + } + ] +} \ No newline at end of file diff --git a/entry/src/main/resources/base/graphic/background_ability_main.xml b/entry/src/main/resources/base/graphic/background_ability_main.xml new file mode 100644 index 0000000..c0c0a3d --- /dev/null +++ b/entry/src/main/resources/base/graphic/background_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/entry/src/main/resources/base/graphic/toast_background_shape.xml b/entry/src/main/resources/base/graphic/toast_background_shape.xml new file mode 100644 index 0000000..a9422d6 --- /dev/null +++ b/entry/src/main/resources/base/graphic/toast_background_shape.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/entry/src/main/resources/base/layout/ability_main.xml b/entry/src/main/resources/base/layout/ability_main.xml new file mode 100644 index 0000000..826f9c8 --- /dev/null +++ b/entry/src/main/resources/base/layout/ability_main.xml @@ -0,0 +1,122 @@ + + + + + + + + + +