Save Registered Host on Android

This commit is contained in:
Florian Märkl 2019-10-15 20:13:57 +02:00
commit da73d4e26e
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
8 changed files with 97 additions and 25 deletions

View file

@ -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
)
}

View file

@ -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?
)

View file

@ -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<List<RegisteredHost>>
@Query("SELECT * FROM registered_host WHERE ps4_mac == :mac LIMIT 1")
fun getByMac(mac: MacAddress): Maybe<RegisteredHost>
@Insert
fun insert(host: RegisteredHost): Single<Long>
}

View file

@ -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()

View file

@ -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()

View file

@ -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<String> = 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()
}
}

View file

@ -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"/>
</vector>

View file

@ -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