From 00a2e8adffbe2e24bf2082cbc2f71105c34b49ae Mon Sep 17 00:00:00 2001 From: Jiangliwu Date: Tue, 4 Dec 2018 23:05:14 +0800 Subject: [PATCH 1/8] remove header, fix wifi connect response, etc .. --- beacon.cc | 84 +++++++++++++------------------ beacon.h | 5 ++ bleconfd.ini | 2 +- blepacket.cc | 135 -------------------------------------------------- blepacket.h | 58 ---------------------- gattServer.cc | 5 +- main.cc | 3 ++ wpaControl.cc | 23 +++++++-- 8 files changed, 67 insertions(+), 248 deletions(-) delete mode 100644 blepacket.cc delete mode 100644 blepacket.h diff --git a/beacon.cc b/beacon.cc index 9a7210a..773a254 100644 --- a/beacon.cc +++ b/beacon.cc @@ -204,47 +204,6 @@ hex_dump(int width, unsigned char* buf, int len) printf("\n"); } - -/** - * update device name, not sure why it not worked as expected ??? - * keep it for now - * @param hdev the device id - * @param deviceName the device name - */ -void -cmdName(int hdev, char const* deviceName) -{ - int dd = hci_open_dev(hdev); - if (dd < 0) - { - XLOG_ERROR("Can't open device hci%d: %s (%d)", hdev, strerror(errno), errno); - exit(1); - } - - if (hci_write_local_name(dd, deviceName, 2000) < 0) - { - XLOG_ERROR("Can't change local name on hci%d: %s (%d)", hdev, strerror(errno), errno); - exit(1); - } - - char name[249]; - if (hci_read_local_name(dd, sizeof(name), name, 1000) < 0) - { - XLOG_ERROR("Can't read local name on hci%d: %s (%d)", hdev, strerror(errno), errno); - exit(1); - } - - for (int i = 0; i < 248 && name[i]; i++) - { - if ((unsigned char) name[i] < 32 || name[i] == 127) - name[i] = '.'; - } - name[248] = '\0'; - - XLOG_INFO("Device Name: '%s'", name); - hci_close_dev(dd); -} - string getDeviceNameFromFile() { @@ -270,13 +229,14 @@ updateDeviceName(string const& name) // device name is same as new name, skip it if (!name.compare(getDeviceNameFromFile())) { + XLOG_INFO("current BLE name is %s", name.c_str()); return; } char cmd_buffer[256]; sprintf(cmd_buffer, "sh -c \"echo 'PRETTY_HOSTNAME=%s' > /etc/machine-info\"", name.c_str()); runCommand(cmd_buffer); runCommand("service bluetooth restart"); - XLOG_DEBUG("device set new name = %s", getDeviceNameFromFile().c_str()); + XLOG_INFO("BLE set new name = %s", getDeviceNameFromFile().c_str()); } /** @@ -382,15 +342,31 @@ parseArgs(string str) } /** - * start up beacon - * @param s the expected device name + * let BLE discoverable */ -void -startBeacon(std::string const& s) +void +cmdScan(int ctl, int hdev, char const* opt) { + struct hci_dev_req dr; + + dr.dev_id = hdev; + dr.dev_opt = SCAN_DISABLED; + if (!strcmp(opt, "iscan")) + dr.dev_opt = SCAN_INQUIRY; + else if (!strcmp(opt, "pscan")) + dr.dev_opt = SCAN_PAGE; + else if (!strcmp(opt, "piscan")) + dr.dev_opt = SCAN_PAGE | SCAN_INQUIRY; + + if (ioctl(ctl, HCISETSCAN, (unsigned long) &dr) < 0) { + XLOG_ERROR("Can't set scan mode on hci%d: %s (%d)", hdev, strerror(errno), errno); + exit(1); + } +} - // updateDeviceName(s.c_str()); - +void +reinitializeBLE() +{ int ctl = 0; if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)) < 0) { @@ -417,6 +393,7 @@ startBeacon(std::string const& s) cmdDown(ctl, di.dev_id); cmdUp(ctl, di.dev_id); + cmdScan(ctl, di.dev_id, "piscan"); cmdNoleadv(di.dev_id); std::string startUpCmd01(appSettings_get_ble_value("ble_init_cmd01")); @@ -425,5 +402,14 @@ startBeacon(std::string const& s) std::string startUpCmd02(appSettings_get_ble_value("ble_init_cmd02")); hcitoolCmd(di.dev_id, parseArgs(startUpCmd02)); cmdLeadv(di.dev_id); - cmdName(di.dev_id, s.c_str()); +} + +/** + * start up beacon + * @param s the expected device name + */ +void +startBeacon(std::string const& s) +{ + updateDeviceName(s.c_str()); } \ No newline at end of file diff --git a/beacon.h b/beacon.h index f393610..5f89053 100644 --- a/beacon.h +++ b/beacon.h @@ -26,4 +26,9 @@ */ void startBeacon(std::string const& s); +/** + * we need clean all BLE connection and staus when ready to accept new client + */ +void reinitializeBLE(); + #endif diff --git a/bleconfd.ini b/bleconfd.ini index 2440988..ebfeb2b 100644 --- a/bleconfd.ini +++ b/bleconfd.ini @@ -1,5 +1,5 @@ [ble] -ble_name=RPI-BLE02 +ble_name=RPI-BLE-NEW ble_device_id=0 ble_init_cmd01=0x08 0x0008 1F 02 01 05 03 03 12 18 03 19 C1 03 0E 09 58 66 69 6E 69 74 79 2E 78 43 61 6D 32 04 FF 5D 00 04 ble_init_cmd02=0x08 0x0006 A0 00 A0 00 00 00 00 00 00 00 00 00 00 07 00 diff --git a/blepacket.cc b/blepacket.cc deleted file mode 100644 index f29e0b7..0000000 --- a/blepacket.cc +++ /dev/null @@ -1,135 +0,0 @@ -// -// Copyright [2018] [jacobgladish@yahoo.com] -// -// 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 implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#include "blepacket.h" - -#include -#include -#include -#include - -static uint16_t kFirstFrameBit = {0x0001}; -static uint16_t kContinuationFrameBit = {0x0002}; -static uint16_t kFrameVersion = {0x7}; - -BLEPacket::Fragmenter::Fragmenter(char const* s, int n, int fragment_size) - : m_data(reinterpret_cast(s)) - , m_index(0) - , m_header(0) - , m_length(n) - , m_fragment_size(fragment_size) -{ -} - -bool -BLEPacket::Fragmenter::nextFrameWithHeader(uint8_t* buff, int* n) -{ - uint8_t const* p = nullptr; - uint32_t header = 0; - - memset(buff, 0, *n); - - bool b = nextFrame(&p, n, &header); - - memcpy(buff, &header, sizeof(header)); - memcpy(buff + sizeof(header), p, *n); - - return b; -} - -bool -BLEPacket::Fragmenter::nextFrame(uint8_t const** p, int* n, uint32_t* header) -{ - if (!p || !n) - return false; - - assert(m_index <= m_length); - if (m_index == m_length) - return false; - - if (header) - { - *header = 0; - *header |= (kFrameVersion << 28); - if (m_index == 0) - *header |= (kFirstFrameBit << 16); - else - *header |= (kContinuationFrameBit << 16); - } - - // account for header - int payload_length = m_fragment_size; - if ((m_index + m_fragment_size) > m_length) - payload_length = (m_length - m_index); - - *p = m_data + m_index; - *n = payload_length; - - m_index += payload_length; - - if (header) - *header |= htons(*n & 0x0000ffff); - - return true; -} - -void -BLEPacket::printHeader(int n) -{ - uint16_t flags = (n >> 16 & 0xffff); - printf("["); - for (int i = 0; i < 16; ++i) - { - printf("%0d", (flags >> (15 - i)) & 1); - } - printf("]"); - printf("%05d\n", frameLengthFromHeader(n)); -} - -uint16_t -BLEPacket::frameLengthFromHeader(uint16_t n) -{ - return ntohs(0x0000ffff & n); -} - -bool -BLEPacket::isContinuationFrame(uint32_t header) -{ - return ((0x00ff0000 & header) >> 15) > 1; -} - - -bool -BLEPacket::isFirstFrame(uint32_t header) -{ - return (0x00ff0000 & header) >> 16 == 1; -} - - -bool -BLEPacket::isContainsHeader(uint8_t* frame) -{ - int header = *reinterpret_cast(frame); - return header >> 28 == kFrameVersion && isFirstFrame(header); -} - -void -BLEPacket::printFrame(uint8_t* frame) -{ - int* header = reinterpret_cast(frame); - printf("---> HDR:"); - printHeader(*header); - printf("---> PKT:%.*s\n", frameLengthFromHeader(*header), (char*) (frame + 4)); -} diff --git a/blepacket.h b/blepacket.h deleted file mode 100644 index 2bc3623..0000000 --- a/blepacket.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright [2018] [jacobgladish@yahoo.com] -// -// 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 implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -#ifndef __BLE_PACKET_H__ -#define __BLE_PACKET_H__ - -#include - -#define HEADER_LENGTH (4) - -class BLEPacket -{ -public: - class Fragmenter - { - public: - Fragmenter(char const* s, int n, int fragment_size); - - public: - bool nextFrameWithHeader(uint8_t* buff, int* n); - - bool nextFrame(uint8_t const** p, int* n, uint32_t* header = nullptr); - - private: - uint8_t const* m_data; - int m_index; - int m_header; - int m_length; - int m_fragment_size; - }; - -public: - static void printHeader(int n); - - static uint16_t frameLengthFromHeader(uint16_t n); - - static bool isContinuationFrame(uint32_t header); - - static bool isFirstFrame(uint32_t header); - - static bool isContainsHeader(uint8_t* frame); - - static void printFrame(uint8_t* frame); -}; - -#endif diff --git a/gattServer.cc b/gattServer.cc index b1dace8..09badd9 100644 --- a/gattServer.cc +++ b/gattServer.cc @@ -16,6 +16,7 @@ #include "defs.h" #include "gattServer.h" #include "xLog.h" +#include "beacon.h" #include #include @@ -230,6 +231,8 @@ GattServer::init() std::shared_ptr GattServer::accept(GattClient::DeviceInfoProvider const& p) { + // clean all connection + reinitializeBLE(); mainloop_init(); sockaddr_l2 peer_addr; @@ -451,7 +454,7 @@ GattClient::onEPollRead( uint8_t opcode, bt_att* UNUSED_PARAM(att)) { - uint32_t value = 1234; + uint32_t value = m_outgoing_queue.size(); XLOG_DEBUG("onEPollRead(offset=%d, opcode=%d)", offset, opcode); diff --git a/main.cc b/main.cc index dd8f257..d117f95 100644 --- a/main.cc +++ b/main.cc @@ -417,6 +417,9 @@ int main(int argc, char* argv[]) exit(1); } + std::string bleName(appSettings_get_ble_value("ble_name")); + startBeacon(bleName); + // TODO: add command line to run various tests // pthread_t thread; // pthread_create(&thread, nullptr, &run_test, &rpc_dispatcher); diff --git a/wpaControl.cc b/wpaControl.cc index f9f45c4..120ef54 100644 --- a/wpaControl.cc +++ b/wpaControl.cc @@ -278,8 +278,12 @@ watch_wlan_state(void* UNUSED_PARAM(argp)) { bool running = true; int pre_req_id = connect_req_id; + uint32_t timeout_time = 1000 * 1000 * 15; // 15 seconds XLOG_DEBUG("watch_wlan_state create new thread to check state, req_id= %d", pre_req_id); usleep(1000 * 1200); // wait some time then start check + uint32_t used_time = 1000 * 1200; + uint32_t loop_time = 1000 * 100; // 100 ms + // the state should be from "4WAY_HANDSHAKE" to something else while (true) { @@ -291,11 +295,10 @@ watch_wlan_state(void* UNUSED_PARAM(argp)) std::string state = get_wlan_state(); - if (!state.compare("SCANNING") - || !state.compare("DISCONNECTED") + if ( !state.compare("DISCONNECTED") || !state.compare("INACTIVE") || !state.compare("INTERFACE_DISABLED") - ) // connect failed + ) // connect failed, return directly { cJSON* rsp = wpaControl_createAsyncConnectResponse("connect failed, maybe password wrong or something else", state); @@ -311,8 +314,20 @@ watch_wlan_state(void* UNUSED_PARAM(argp)) enqueue_async_message(rsp); running = false; + } else // other states may between COMPLETED with 4WAY_HANDSHAKE, so we need ignore this + { + used_time += loop_time; + } + + // timeout + if (used_time >= timeout_time && running) + { + cJSON* rsp = wpaControl_createAsyncConnectResponse("connect failed, timeout", + state); + enqueue_async_message(rsp); + running = false; } - usleep(1000 * 100); // 200 ms check + usleep(loop_time); } } From 602f2b04f143a8b230a41d948668fa4a526cac30 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Wed, 5 Dec 2018 13:55:35 +1100 Subject: [PATCH 2/8] Add Android client app to Git --- AndroidClientApp/.gitignore | 11 ++ AndroidClientApp/.idea/codeStyles/Project.xml | 29 +++ AndroidClientApp/.idea/gradle.xml | 18 ++ AndroidClientApp/.idea/misc.xml | 38 ++++ AndroidClientApp/.idea/runConfigurations.xml | 12 ++ AndroidClientApp/app/.gitignore | 1 + AndroidClientApp/app/build.gradle | 28 +++ AndroidClientApp/app/proguard-rules.pro | 21 +++ .../app/src/main/AndroidManifest.xml | 26 +++ .../drawable-v24/ic_launcher_foreground.xml | 34 ++++ .../res/drawable/ic_launcher_background.xml | 170 +++++++++++++++++ .../app/src/main/res/layout/activity_main.xml | 65 +++++++ .../app/src/main/res/layout/dialog_wifi.xml | 51 ++++++ .../app/src/main/res/layout/spinner_item.xml | 13 ++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2963 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4905 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2060 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2783 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4490 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6895 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6387 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10413 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9128 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15132 bytes .../app/src/main/res/values/colors.xml | 6 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 11 ++ AndroidClientApp/build.gradle | 27 +++ AndroidClientApp/gradle.properties | 14 ++ .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + AndroidClientApp/gradlew | 172 ++++++++++++++++++ AndroidClientApp/gradlew.bat | 84 +++++++++ AndroidClientApp/settings.gradle | 1 + 36 files changed, 850 insertions(+) create mode 100644 AndroidClientApp/.gitignore create mode 100644 AndroidClientApp/.idea/codeStyles/Project.xml create mode 100644 AndroidClientApp/.idea/gradle.xml create mode 100644 AndroidClientApp/.idea/misc.xml create mode 100644 AndroidClientApp/.idea/runConfigurations.xml create mode 100644 AndroidClientApp/app/.gitignore create mode 100644 AndroidClientApp/app/build.gradle create mode 100644 AndroidClientApp/app/proguard-rules.pro create mode 100644 AndroidClientApp/app/src/main/AndroidManifest.xml create mode 100644 AndroidClientApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 AndroidClientApp/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 AndroidClientApp/app/src/main/res/layout/activity_main.xml create mode 100644 AndroidClientApp/app/src/main/res/layout/dialog_wifi.xml create mode 100644 AndroidClientApp/app/src/main/res/layout/spinner_item.xml create mode 100644 AndroidClientApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 AndroidClientApp/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 AndroidClientApp/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 AndroidClientApp/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 AndroidClientApp/app/src/main/res/values/colors.xml create mode 100644 AndroidClientApp/app/src/main/res/values/strings.xml create mode 100644 AndroidClientApp/app/src/main/res/values/styles.xml create mode 100644 AndroidClientApp/build.gradle create mode 100644 AndroidClientApp/gradle.properties create mode 100644 AndroidClientApp/gradle/wrapper/gradle-wrapper.jar create mode 100644 AndroidClientApp/gradle/wrapper/gradle-wrapper.properties create mode 100755 AndroidClientApp/gradlew create mode 100644 AndroidClientApp/gradlew.bat create mode 100644 AndroidClientApp/settings.gradle diff --git a/AndroidClientApp/.gitignore b/AndroidClientApp/.gitignore new file mode 100644 index 0000000..fd45b12 --- /dev/null +++ b/AndroidClientApp/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea/caches/build_file_checksums.ser +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/AndroidClientApp/.idea/codeStyles/Project.xml b/AndroidClientApp/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..30aa626 --- /dev/null +++ b/AndroidClientApp/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidClientApp/.idea/gradle.xml b/AndroidClientApp/.idea/gradle.xml new file mode 100644 index 0000000..7ac24c7 --- /dev/null +++ b/AndroidClientApp/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/AndroidClientApp/.idea/misc.xml b/AndroidClientApp/.idea/misc.xml new file mode 100644 index 0000000..e0d5b93 --- /dev/null +++ b/AndroidClientApp/.idea/misc.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidClientApp/.idea/runConfigurations.xml b/AndroidClientApp/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/AndroidClientApp/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/AndroidClientApp/app/.gitignore b/AndroidClientApp/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/AndroidClientApp/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/AndroidClientApp/app/build.gradle b/AndroidClientApp/app/build.gradle new file mode 100644 index 0000000..a8cae33 --- /dev/null +++ b/AndroidClientApp/app/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "bleconfd.tc.com.bleconfd_example" + minSdkVersion 26 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/AndroidClientApp/app/proguard-rules.pro b/AndroidClientApp/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/AndroidClientApp/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/AndroidClientApp/app/src/main/AndroidManifest.xml b/AndroidClientApp/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..30c9cd5 --- /dev/null +++ b/AndroidClientApp/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AndroidClientApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/AndroidClientApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/AndroidClientApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/AndroidClientApp/app/src/main/res/drawable/ic_launcher_background.xml b/AndroidClientApp/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/AndroidClientApp/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AndroidClientApp/app/src/main/res/layout/activity_main.xml b/AndroidClientApp/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..c81d561 --- /dev/null +++ b/AndroidClientApp/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + +