mirror of
https://github.com/CopterExpress/clover.git
synced 2026-05-26 21:19:35 +00:00
Added Android app source code (#94)
* Added android app * Added Google Play picture * Update rc.md * Update rc.md * Update rc.md * Update rc.md * Update rc.md * Update rc.md * Create android.md * Update SUMMARY.md * Update android.md * Update android.md
This commit is contained in:
committed by
Oleg Kalachev
parent
7e2cea7425
commit
53cc575c23
BIN
docs/assets/google_play.png
Normal file
BIN
docs/assets/google_play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
@@ -51,6 +51,7 @@
|
||||
* Проекты на базе Клевера
|
||||
* [Шаровая защита коптера](shield.md)
|
||||
* [Распознавание лиц](face_recognition.md)
|
||||
* [Пульт на Андроид](android.md)
|
||||
* [CopterHack-2018](copterhack2018.md)
|
||||
* [CopterHack-2017](copterhack2017.md)
|
||||
* Дополнительные материалы
|
||||
|
||||
144
docs/ru/android.md
Normal file
144
docs/ru/android.md
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
# Пульт на Android
|
||||
|
||||
Все владельцы мобильных устройств фирмы *Apple* ещё морозным январем 2018го обзавелись приятным мобильным приложением под *iOS* для пилотирования квадрокоптеров с помощью **WiFi**. И вот, спустя год вышло такое же приложение но уже для другой операционной системы. Актуальную версию вы можете скачать [**тут**](https://vk.com/away.php?to=https%3A%2F%2Fplay.google.com%2Fstore%2Fapps%2Fdetails%3Fid%3Dexpress.copter.cleverrc&cc_key=)
|
||||
|
||||
|
||||
## Введение
|
||||
|
||||
В данной статье я расскажу вам о том, как можно написать свой или доработать уже имеющийся пульт для Андроид своими руками. Для работы будем использовать модный язык *Kotlin*, а в качестве среды разработки возьмем *Android Studio*. Для тех кто ни разу ей не пользовался рекомендую к ознакомлению следующие [*материалы*](https://www.google.com/search?ei=xQxDXMH0C8OOmgW4mYigDQ&q=%D0%A7%D1%82%D0%BE+%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C+%D0%B5%D1%81%D0%BB%D0%B8+%D1%8F+%D0%BD%D0%B5+%D1%83%D0%BC%D0%B5%D1%8E+%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C+%D0%BF%D0%BE%D0%B4+%D0%B0%D0%BD%D0%B4%D1%80%D0%BE%D0%B8%D0%B4%3F&oq=%D0%A7%D1%82%D0%BE+%D0%B4%D0%B5%D0%BB%D0%B0%D1%82%D1%8C+%D0%B5%D1%81%D0%BB%D0%B8+%D1%8F+%D0%BD%D0%B5+%D1%83%D0%BC%D0%B5%D1%8E+%D0%BF%D0%B8%D1%81%D0%B0%D1%82%D1%8C+%D0%BF%D0%BE%D0%B4+%D0%B0%D0%BD%D0%B4%D1%80%D0%BE%D0%B8%D0%B4%3F&gs_l=psy-ab.3...4413.17423..17726...9.0..2.442.4577.45j5j1j0j1....2..0....1..gws-wiz.....6..0i71j35i39j0i131j0j0i67j0i131i67j0i22i30j33i22i29i30j33i21j33i160.0bZz-WGxoHY). Весь код приложения можно найти [**тут**](https://github.com/Tennessium/android). Чтобы скопировать его в определенную папку выполните следующую команду:
|
||||
```Bash
|
||||
git clone https://github.com/Tennessium/android
|
||||
```
|
||||
Чтобы вы смогли полностью понять устройство приложения я расскажу вам о каждом этапе создания проекта.
|
||||
|
||||
## Обертка
|
||||
|
||||
|
||||
|
||||
Начнем с самого простого - внешнего вида нашего приложения. На [**гитхабе**](https://github.com/CopterExpress/clever/tree/master/apps/ios) вы можете найти *HTML*, *CSS* и *JavaScript* файлы, это и есть веб страница с которой будет происходить управление коптером. Чтобы эта страница отображалась у нас в приложении надо:
|
||||
|
||||
|
||||
|
||||
1. Создать папку **assets** в главной папке приложения **app**
|
||||
|
||||
2. Добавить в нее файлы **clever.svg**, **index.html**, **roslib.js**, **telemetry.js** и **main.css** из репозитория выше
|
||||
|
||||
3. Так же добавьте **main.js**, но уже [**отсюда**](https://github.com/Tennessium/android/tree/master/assets). В этом репозитории находится весь код пульта для Андроид, кстати. Так что можно было копировать файлы отсюда
|
||||
|
||||
|
||||
|
||||
Если вы дошли до этого этапа то у вас уже есть необходимая веб страница, поздравляю! Теперь нам надо её как-то отобразить в приложении. Для этого в классе вашего *activity* в методе **onCreate** необходимо написать следующий код:
|
||||
|
||||
|
||||
|
||||
```Kotlin
|
||||
main_web.loadUrl("file:///android_asset/index.html")
|
||||
```
|
||||
|
||||
Где *main_web* - id вашего *WebView*, который должен находится в *xml* файле выбранного вами *activity*.
|
||||
|
||||
|
||||
|
||||
К сожалению, пульт для управления коптером требует всего экрана устройства, а элементы интерфейса системы мешают полноценному использованию программы. Для этого надо в начале метода **onCreate** вызвать следующую функцию:
|
||||
|
||||
```Kotlin
|
||||
private fun fullScreenCall() {
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
|
||||
if (Build.VERSION.SDK_INT < 19) {
|
||||
val v = this.window.decorView
|
||||
v.systemUiVisibility = View.GONE
|
||||
} else {
|
||||
//for higher api versions.
|
||||
val decorView = window.decorView
|
||||
val uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
decorView.systemUiVisibility = uiOptions
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Данная функция позволяет избавится от элементов интерфейса системы. Идем дальше.
|
||||
|
||||
Вот так выглядит пульт на этом этапе:
|
||||
|
||||
<img src="../assets/IMG_4397.PNG" width="50%">
|
||||
|
||||
Если вы запустите приложение, то заметите что стики не работают. Это происходит по тому, что на нашей странице отключен *JavaScript*. чтобы его включить надо прописать следующее:
|
||||
|
||||
```Kotlin
|
||||
main_web.settings.apply {
|
||||
domStorageEnabled = true
|
||||
javaScriptEnabled = true
|
||||
loadWithOverviewMode = true
|
||||
useWideViewPort = true
|
||||
setSupportZoom(false)
|
||||
}
|
||||
```
|
||||
|
||||
Этим куском кода мы разрешаем странице использовать *JavaScript* и заодно готовимся к следующему этапу - **логике**.
|
||||
|
||||
## Прием данных с веб страницы
|
||||
|
||||
Чтобы телефон мог принимать данные с *HTML страницы*, надо создать класс для взаимодействия с веб интерфейсом
|
||||
|
||||
```Kotlin
|
||||
class WebAppInterface(c: Context) {
|
||||
@JavascriptInterface
|
||||
public fun postMessage(message: String) {
|
||||
val data = JSONObject(message)
|
||||
send("255.255.255.255", 35602, pack(
|
||||
data.getInt("x").toShort(),
|
||||
data.getInt("y").toShort(),
|
||||
data.getInt("z").toShort(),
|
||||
data.getInt("r").toShort()))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Данный класс будет получать сообщение с веб страницы отправленное методом *postMessage*, где аргумент *message* - сообщение от страницы.
|
||||
|
||||
Теперь надо связать классы **WebAppInterface** и **MainActivity**. Для этого надо всего лишь добавить одну строку в метод **onCreate**:
|
||||
|
||||
```Kotlin
|
||||
main_web.addJavascriptInterface(WebAppInterface(this), "appInterface")
|
||||
```
|
||||
|
||||
## Отправка данных на коптер
|
||||
|
||||
Вы наверное заметили функцию *send* в классе **WebAppInterface**. Именно она отправляет данные на коптер. Давайте объявим ее **вне классов**:
|
||||
|
||||
```Kotlin
|
||||
fun send(host: String, port: Int, data: ByteArray, senderPort: Int = 0): Boolean {
|
||||
var ret = false
|
||||
var socket: DatagramSocket? = null
|
||||
try {
|
||||
socket = DatagramSocket(senderPort)
|
||||
val address = InetAddress.getByName(host)
|
||||
val packet = DatagramPacket(data, data.size, address, port)
|
||||
socket.send(packet)
|
||||
ret = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
} finally {
|
||||
socket?.close()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
```
|
||||
|
||||
Данная функция отправляет данные при помощи [*протокола пользовательских датаграмм*](https://www.google.com/search?q=udp+%D0%BF%D1%80%D0%BE%D1%82%D0%BE%D0%BA%D0%BE%D0%BB&oq=udp+&aqs=chrome.0.69i59j69i57j35i39j0l3.1434j1j7&sourceid=chrome&ie=UTF-8) на коптер. Программа отправляет **байты**, поэтому неплохо бы было объявить функцию для создания массива **байтов** из четырех переменных:
|
||||
|
||||
```Kotlin
|
||||
fun pack(x: Short, y: Short, z: Short, r: Short): ByteArray {
|
||||
val pump_on_buf: ByteBuffer = ByteBuffer.allocate(8)
|
||||
pump_on_buf.putShort(r)
|
||||
pump_on_buf.putShort(z)
|
||||
pump_on_buf.putShort(y)
|
||||
pump_on_buf.putShort(x)
|
||||
return pump_on_buf.array().reversedArray()
|
||||
}
|
||||
```
|
||||
|
||||
## Итог
|
||||
|
||||
Теперь ваше приложение имеет полный функционал аналога под **iOS**. Можете кастомизировать его как пожелаете. По любым вопросам о приложении можете обращаться в Телеграм @Tenessinum.
|
||||
@@ -1,9 +1,9 @@
|
||||
Управление Клевером со смартфона
|
||||
===
|
||||
|
||||
<a href="https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8"><img src="../assets/appstore.svg"></a>
|
||||
<a href="https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8"><img src="../assets/appstore.svg"></a><a href="https://play.google.com/store/apps/details?id=express.copter.cleverrc"><img src="../assets/google_play.png" width="15%"></a>
|
||||
|
||||
Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение – [iOS](https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8), Android (*work-in-progress*).
|
||||
Для управления Клевером со смартфона через Wi-Fi необходимо установить приложение – [iOS](https://itunes.apple.com/ru/app/clever-rc/id1396166572?mt=8), [Android](https://play.google.com/store/apps/details?id=express.copter.cleverrc).
|
||||
|
||||

|
||||
|
||||
@@ -46,7 +46,7 @@ sudo systemctl restart clever
|
||||
|
||||
Подключите смартфон к [Wi-Fi](wifi.md) сети Клевера (`CLEVER-xxxx`). Приложение должно подключиться с коптеру автоматически. При успешном подключении должны отобразиться текущий [режим](modes.md) и заряд батареи.
|
||||
|
||||
Стики на экране приложения работают так же, как и реальные стики. Для арма коптера подержите левый стик в правом нижнем углу на протяжении нескольких секунд. Для дизарма – в левом нижнем углу.
|
||||
Стики на экране приложения работают так же, как и реальные стики. Для арма коптера подержите левый стик в правом нижнем углу на протяжении нескольких секунд. Для дизарма – в левом нижнем углу.
|
||||
|
||||
Неисправности
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user