Posted at

親フラ検知機を作る ②Android編


はじめに

この記事は、「親フラ検知機を作る ①仕組み編」の続き。


動作

AndroidではUDPを受け取って、その受け取った値によって以下の動作を行います。

'W'を受信 => 画面を特定のWEBページに強制推移

'D'を受信 => 人が近づいていることを画面に通知


コード

説明はコメントの通りです。


UDPを受信


UDP.kt

package com.akakou.sample.oyanoteki

import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import java.io.IOException

object UDP {
var ip = InetAddress.getByName("192.168.xxx.255") // ここは自分のネットワークに合わせて
var port = 5000

fun receive() : Byte {
// UDPの受信
val socket = DatagramSocket(port)
val buffer = ByteArray(1024)
val packet = DatagramPacket(buffer, 0, buffer.size)

val result = try {
socket.receive(packet)
buffer[0]
} catch (e: IOException) {
0.toByte()
}

socket.close()

return result
}
}



サービス


MainService.kt

package com.akakou.sample.oyanoteki

import android.content.Intent
import android.app.IntentService
import android.net.Uri

import android.widget.Toast
import android.os.Handler
import android.os.Looper
import kotlinx.coroutines.experimental.delay
import java.lang.Thread.sleep
import kotlin.concurrent.thread

class MainService : IntentService("MainService") {
var intent: Intent? = null

override fun onHandleIntent(intent: Intent?) {
val handler = Handler(Looper.getMainLooper())
handler.post {
Toast.makeText(applicationContext, "あなたの部屋を守ります", Toast.LENGTH_SHORT).show()
}

while (true) {
try {
var data = UDP.receive() // UDPを受信

if (data == 'W'.toByte()) {
// もし受信したデータが'W'だったら、
// Toastを表示する。
handler.post {
Toast.makeText(applicationContext, "奴が近づいている…\n気をつけろ…", Toast.LENGTH_SHORT).show()
}
}

if (data == 'D'.toByte()) {
// もし受信したデータが'D'だったら、
// Yahooニュースをブラウザで開く
val uri = Uri.parse("https://news.yahoo.co.jp/hl?c=bus")
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)
}

} catch (err: Exception) {
handler.post {
Toast.makeText(applicationContext, "$err", Toast.LENGTH_SHORT).show()
}
}
}
}
}



アクティビティ


MainActivity

package com.akakou.sample.oyanoteki

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
private var serviceIntent : Intent? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// サービスを起動
serviceIntent = Intent(this, MainService::class.java)
startService(serviceIntent)
}
}



デバッグ

デバッグ用のコードを同じネットワーク上のPCで実行する。

(FWの設定で躓かないように)


コード

以下のようなスクリプトを書いた。


client.py

from socket import *

import sys

HOST = ''
PORT = 5000
ADDRESS = "192.168.xxx.255"

s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)

while True:
msg = input("> ")
s.sendto(msg.encode(), (ADDRESS, PORT))
if msg == ".":
break

s.close()
sys.exit()



実行結果

以下のような入力をして正しく動作したか確認する。

> W

> D
>

正しく動作すれば、警告が表示された後、画面がYahooニュースに切り替わるはずである。


次回予告

次回からは@Tsukkeyが、ESP32①(ドア開閉検知)に関する部分をやると思います。