Skip to content

Commit

Permalink
Support rocker move
Browse files Browse the repository at this point in the history
  • Loading branch information
fuqiuluo committed Oct 15, 2024
1 parent cf17bee commit 50361fa
Show file tree
Hide file tree
Showing 18 changed files with 562 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package moe.fuqiuluo.portal.android.coro

import kotlinx.coroutines.channels.Channel

class CoroutineController {
private val controlChannel = Channel<ControlCommand>(Channel.UNLIMITED)
var isPaused = false

suspend fun controlledCoroutine() {
checkControl()
}

private suspend fun checkControl() {
controlChannel.tryReceive().getOrNull()?.let {
when (it) {
ControlCommand.Pause -> {
isPaused = true
while (controlChannel.receive() != ControlCommand.Resume) {
// do nothing
}
isPaused = false
}
ControlCommand.Resume -> {}
}
}
}

fun pause() {
controlChannel.trySend(ControlCommand.Pause)
}

fun resume() {
controlChannel.trySend(ControlCommand.Resume)
}
}

enum class ControlCommand {
Pause,
Resume
}
93 changes: 93 additions & 0 deletions app/src/main/java/moe/fuqiuluo/portal/service/MockServiceHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package moe.fuqiuluo.portal.service
import android.location.LocationManager
import android.os.Bundle
import android.util.Log
import moe.fuqiuluo.xposed.utils.FakeLoc

object MockServiceHelper {
const val PROVIDER_NAME = "portal"
Expand Down Expand Up @@ -79,6 +80,98 @@ object MockServiceHelper {
return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun setBearing(locationManager: LocationManager, bearing: Double): Boolean {
if (!::randomKey.isInitialized) {
return false
}
val rely = Bundle()
rely.putString("command_id", "set_bearing")
rely.putDouble("bearing", bearing)
return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun setSpeed(locationManager: LocationManager, speed: Float): Boolean {
if (!::randomKey.isInitialized) {
return false
}
val rely = Bundle()
rely.putString("command_id", "set_speed")
rely.putFloat("speed", speed)
return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun setAltitude(locationManager: LocationManager, altitude: Double): Boolean {
if (!::randomKey.isInitialized) {
return false
}
val rely = Bundle()
rely.putString("command_id", "set_altitude")
rely.putDouble("altitude", altitude)
return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun setSpeedAmplitude(locationManager: LocationManager, speedAmplitude: Double): Boolean {
if (!::randomKey.isInitialized) {
return false
}
val rely = Bundle()
rely.putString("command_id", "set_speed_amp")
rely.putDouble("speed_amplitude", speedAmplitude)
return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun getSpeed(locationManager: LocationManager): Float? {
if (!::randomKey.isInitialized) {
return null
}
val rely = Bundle()
rely.putString("command_id", "get_speed")
if(locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)) {
return rely.getFloat("speed")
}
return null
}

fun getBearing(locationManager: LocationManager): Float? {
if (!::randomKey.isInitialized) {
return null
}
val rely = Bundle()
rely.putString("command_id", "get_bearing")
if(locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)) {
return rely.getFloat("bearing")
}
return null
}

fun getAltitude(locationManager: LocationManager): Double? {
if (!::randomKey.isInitialized) {
return null
}
val rely = Bundle()
rely.putString("command_id", "get_altitude")
if(locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)) {
return rely.getDouble("altitude")
}
return null
}

fun move(locationManager: LocationManager, distance: Double, bearing: Double): Boolean {
if (!::randomKey.isInitialized) {
return false
}
val rely = Bundle()
rely.putString("command_id", "move")
rely.putDouble("n", distance)
rely.putDouble("bearing", bearing)

if (FakeLoc.enableDebugLog) {
Log.d("MockServiceHelper", "move: distance=$distance, bearing=$bearing")
}

return locationManager.sendExtraCommand(PROVIDER_NAME, randomKey, rely)
}

fun setLocation(locationManager: LocationManager, lat: Double, lon: Double): Boolean {
return updateLocation(locationManager, lat, lon, "=")
}
Expand Down
21 changes: 16 additions & 5 deletions app/src/main/java/moe/fuqiuluo/portal/ui/mock/MockFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@ package moe.fuqiuluo.portal.ui.mock

import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.CheckedTextView
import android.widget.Toast
import androidx.core.content.ContextCompat
Expand All @@ -34,6 +30,7 @@ import moe.fuqiuluo.portal.ext.selectLocation
import moe.fuqiuluo.portal.service.MockServiceHelper
import moe.fuqiuluo.portal.ui.viewmodel.MockServiceViewModel
import moe.fuqiuluo.portal.ui.viewmodel.MockViewModel
import moe.fuqiuluo.xposed.utils.FakeLoc

class MockFragment : Fragment() {
private var _binding: FragmentMockBinding? = null
Expand Down Expand Up @@ -98,17 +95,30 @@ class MockFragment : Fragment() {
rocker.show()
} else {
rocker.hide()
rockerCoroutineController.pause()
}
}
}

rocker.setRockerListener(object: RockerView.Companion.OnMoveListener {
override fun onAngle(angle: Double) {
Log.d("Rocker", "angle: $angle")
MockServiceHelper.setBearing(locationManager!!, angle)
FakeLoc.bearing = angle
FakeLoc.hasBearings = true
}

override fun onLockChanged(isLocked: Boolean) {
isRockerLocked = isLocked
}

override fun onFinished() {
if (!isRockerLocked) {
rockerCoroutineController.pause()
}
}

override fun onStarted() {
rockerCoroutineController.resume()
}
})
}
Expand Down Expand Up @@ -257,6 +267,7 @@ class MockFragment : Fragment() {
binding.rocker.isClickable = false
binding.rocker.toggle()
mockServiceViewModel.rocker.hide()
mockServiceViewModel.rockerCoroutineController.pause()
binding.rocker.isClickable = true
}
} finally {
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/moe/fuqiuluo/portal/ui/mock/Rocker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import moe.fuqiuluo.portal.R
import moe.fuqiuluo.portal.android.widget.RockerView
import moe.fuqiuluo.portal.ext.rockerCoords
Expand Down Expand Up @@ -50,6 +51,10 @@ class Rocker(private val activity: Activity): View.OnTouchListener {
layoutParams.y = rockerCoords.second

root.setOnTouchListener(this)

root.findViewById<View>(R.id.expand_menu).setOnClickListener {
Toast.makeText(activity, "暂不支持", Toast.LENGTH_SHORT).show()
}
}

fun show() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ package moe.fuqiuluo.portal.ui.viewmodel

import android.app.Activity
import android.location.LocationManager
import android.util.Log
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import moe.fuqiuluo.portal.android.coro.CoroutineController
import moe.fuqiuluo.portal.service.MockServiceHelper
import moe.fuqiuluo.portal.ui.mock.HistoricalLocation
import moe.fuqiuluo.portal.ui.mock.Rocker
import moe.fuqiuluo.xposed.utils.FakeLoc

class MockServiceViewModel: ViewModel() {
lateinit var rocker: Rocker
Expand All @@ -19,10 +25,25 @@ class MockServiceViewModel: ViewModel() {

var selectedLocation: HistoricalLocation? = null

var isRockerLocked = false
val rockerCoroutineController = CoroutineController()

fun initRocker(activity: Activity): Rocker {
if (!::rocker.isInitialized) {
rocker = Rocker(activity)
}

rockerCoroutineController.pause()
GlobalScope.launch {
do {
delay(1000)
rockerCoroutineController.controlledCoroutine()

if(!MockServiceHelper.move(locationManager!!, FakeLoc.speed, FakeLoc.bearing)) {
Log.e("MockServiceViewModel", "Failed to move")
}
} while (true)
}
return rocker
}

Expand Down
Loading

0 comments on commit 50361fa

Please sign in to comment.