From da73d4e26e0acc47317d7be8ae66a161bba35df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Tue, 15 Oct 2019 20:13:57 +0200 Subject: [PATCH] Save Registered Host on Android --- .../com/metallic/chiaki/common/MacAddress.kt | 23 ++++++++ .../com/metallic/chiaki/common/ManualHost.kt | 2 +- .../metallic/chiaki/common/RegisteredHost.kt | 24 ++++++++- .../com/metallic/chiaki/main/MainActivity.kt | 8 --- .../chiaki/regist/RegistExecuteActivity.kt | 7 ++- .../chiaki/regist/RegistExecuteViewModel.kt | 54 +++++++++++++++---- .../main/res/drawable/ic_console_ready.xml | 2 +- android/build.gradle | 2 +- 8 files changed, 97 insertions(+), 25 deletions(-) diff --git a/android/app/src/main/java/com/metallic/chiaki/common/MacAddress.kt b/android/app/src/main/java/com/metallic/chiaki/common/MacAddress.kt index 435a7b2..bc297fb 100644 --- a/android/app/src/main/java/com/metallic/chiaki/common/MacAddress.kt +++ b/android/app/src/main/java/com/metallic/chiaki/common/MacAddress.kt @@ -17,8 +17,22 @@ package com.metallic.chiaki.common +import java.nio.ByteBuffer +import java.nio.ByteOrder + class MacAddress(v: Long) { + constructor(data: ByteArray) : this( + if(data.size != 6) + throw IllegalArgumentException("Data has invalid length for MAC") + else + data.let { + val buf = ByteBuffer.allocate(8) + buf.put(it, 0, 6) + buf.order(ByteOrder.LITTLE_ENDIAN) + buf.getLong(0) + }) + val value: Long = v and 0xffffffffffff override fun equals(other: Any?): Boolean = @@ -28,4 +42,13 @@ class MacAddress(v: Long) super.equals(other) override fun hashCode() = value.hashCode() + + override fun toString(): String = "%02x:%02x:%02x:%02x:%02x:%02x".format( + value and 0xff, + (value shr 0x8) and 0xff, + (value shr 0x10) and 0xff, + (value shr 0x18) and 0xff, + (value shr 0x20) and 0xff, + (value shr 0x28) and 0xff + ) } \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/common/ManualHost.kt b/android/app/src/main/java/com/metallic/chiaki/common/ManualHost.kt index 62f9874..516b9bd 100644 --- a/android/app/src/main/java/com/metallic/chiaki/common/ManualHost.kt +++ b/android/app/src/main/java/com/metallic/chiaki/common/ManualHost.kt @@ -32,7 +32,7 @@ import io.reactivex.Flowable ) ]) data class ManualHost( - @PrimaryKey(autoGenerate = true) val id: Int = 0, + @PrimaryKey(autoGenerate = true) val id: Long = 0, val host: String, @ColumnInfo(name = "registered_host") val registeredHost: Int? ) diff --git a/android/app/src/main/java/com/metallic/chiaki/common/RegisteredHost.kt b/android/app/src/main/java/com/metallic/chiaki/common/RegisteredHost.kt index d985b33..ea161bc 100644 --- a/android/app/src/main/java/com/metallic/chiaki/common/RegisteredHost.kt +++ b/android/app/src/main/java/com/metallic/chiaki/common/RegisteredHost.kt @@ -19,12 +19,15 @@ package com.metallic.chiaki.common import androidx.room.* import androidx.room.ColumnInfo.BLOB +import com.metallic.chiaki.lib.RegistHost import io.reactivex.Flowable +import io.reactivex.Maybe +import io.reactivex.Single @Suppress("ArrayInDataClass") @Entity(tableName = "registered_host") data class RegisteredHost( - @PrimaryKey(autoGenerate = true) val id: Int = 0, + @PrimaryKey(autoGenerate = true) val id: Long = 0, @ColumnInfo(name = "ap_ssid") val apSsid: String?, @ColumnInfo(name = "ap_bssid") val apBssid: String?, @ColumnInfo(name = "ap_key") val apKey: String?, @@ -35,10 +38,29 @@ data class RegisteredHost( @ColumnInfo(name = "rp_key_type") val rpKeyType: Int, @ColumnInfo(name = "rp_key", typeAffinity = BLOB) val rpKey: ByteArray // 0x10 ) +{ + constructor(registHost: RegistHost) : this( + apSsid = registHost.apSsid, + apBssid = registHost.apBssid, + apKey = registHost.apKey, + apName = registHost.apName, + ps4Mac = MacAddress(registHost.ps4Mac), + ps4Nickname = registHost.ps4Nickname, + rpRegistKey = registHost.rpRegistKey, + rpKeyType = registHost.rpKeyType.toInt(), + rpKey = registHost.rpKey + ) +} @Dao interface RegisteredHostDao { @Query("SELECT * FROM registered_host") fun getAll(): Flowable> + + @Query("SELECT * FROM registered_host WHERE ps4_mac == :mac LIMIT 1") + fun getByMac(mac: MacAddress): Maybe + + @Insert + fun insert(host: RegisteredHost): Single } \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt index b98a706..1814a98 100644 --- a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt @@ -40,8 +40,6 @@ import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { - private val disposable = CompositeDisposable() - private lateinit var viewModel: MainViewModel private var discoveryMenuItem: MenuItem? = null @@ -87,12 +85,6 @@ class MainActivity : AppCompatActivity() floatingActionButton.isActivated = floatingActionButton.isExpanded } - override fun onDestroy() - { - super.onDestroy() - disposable.dispose() - } - override fun onStart() { super.onStart() diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt index f6f9588..7cd9559 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt @@ -18,7 +18,6 @@ package com.metallic.chiaki.regist import android.app.Activity -import android.content.ActivityNotFoundException import android.content.Intent import android.os.Bundle import android.text.method.ScrollingMovementMethod @@ -27,6 +26,8 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import com.metallic.chiaki.R +import com.metallic.chiaki.common.ext.viewModelFactory +import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.lib.RegistInfo import kotlinx.android.synthetic.main.activity_regist_execute.* import kotlin.math.max @@ -47,7 +48,9 @@ class RegistExecuteActivity: AppCompatActivity() super.onCreate(savedInstanceState) setContentView(R.layout.activity_regist_execute) - viewModel = ViewModelProviders.of(this).get(RegistExecuteViewModel::class.java) + viewModel = ViewModelProviders + .of(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) }) + .get(RegistExecuteViewModel::class.java) logTextView.setHorizontallyScrolling(true) logTextView.movementMethod = ScrollingMovementMethod() diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt index 8136ace..0173e9d 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt @@ -17,13 +17,22 @@ package com.metallic.chiaki.regist +import android.util.Log +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.metallic.chiaki.common.AppDatabase +import com.metallic.chiaki.common.MacAddress +import com.metallic.chiaki.common.RegisteredHost import com.metallic.chiaki.common.ext.toLiveData import com.metallic.chiaki.lib.* +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.addTo +import io.reactivex.schedulers.Schedulers -class RegistExecuteViewModel: ViewModel() +class RegistExecuteViewModel(val database: AppDatabase): ViewModel() { enum class State { @@ -42,6 +51,8 @@ class RegistExecuteViewModel: ViewModel() val logText: LiveData = log.logText.toLiveData() + private val disposable = CompositeDisposable() + fun start(info: RegistInfo) { if(regist != null) @@ -67,22 +78,43 @@ class RegistExecuteViewModel: ViewModel() { when(event) { - is RegistEventCanceled -> { - _state.postValue(State.STOPPED) - } - is RegistEventFailed -> { - _state.postValue(State.FAILED) - } - is RegistEventSuccess -> { - // TODO: save event.host into db - _state.postValue(State.SUCCESSFUL) - } + is RegistEventCanceled -> _state.postValue(State.STOPPED) + is RegistEventFailed -> _state.postValue(State.FAILED) + is RegistEventSuccess -> registSuccess(event.host) } } + private fun registSuccess(host: RegistHost) + { + _state.postValue(State.SUCCESSFUL) // TODO: more states + + val dao = database.registeredHostDao() + + val mac = MacAddress(host.ps4Mac) + + //val mac = MacAddress(byteArrayOf(0xc0.toByte(), 0xff.toByte(), 0xff.toByte(), 0xee.toByte(), 0xee.toByte(), 0x42)) + + dao.getByMac(mac) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .doOnSuccess { + // TODO: show dialog + Log.i("RegistExecuteViewModel", "already exists") + } + .doOnComplete { + dao.insert(RegisteredHost(host)) + .subscribeOn(Schedulers.io()) + .subscribe() + .addTo(disposable) + } + .subscribe() + .addTo(disposable) + } + override fun onCleared() { super.onCleared() regist?.dispose() + disposable.dispose() } } \ No newline at end of file diff --git a/android/app/src/main/res/drawable/ic_console_ready.xml b/android/app/src/main/res/drawable/ic_console_ready.xml index dff307c..7d7068f 100644 --- a/android/app/src/main/res/drawable/ic_console_ready.xml +++ b/android/app/src/main/res/drawable/ic_console_ready.xml @@ -14,7 +14,7 @@ android:pathData="m7.93,9.425 l-2.324,3.906l121.929,0l2.324,-3.906z" android:strokeAlpha="1" android:strokeWidth="12.74962807" - android:fillColor="#ffae2f" + android:fillColor="#00a7ff" android:strokeColor="#00000000" android:fillAlpha="1"/> diff --git a/android/build.gradle b/android/build.gradle index 4420c59..df8fe1b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:3.5.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files