bugged FileObserver

This commit is contained in:
2023-10-21 00:18:34 +03:00
parent d955b65ea2
commit 23286dd061
5 changed files with 165 additions and 14 deletions
+1
View File
@@ -79,6 +79,7 @@ dependencies {
implementation(libs.ui.graphics) implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview) implementation(libs.ui.tooling.preview)
implementation(libs.material3) implementation(libs.material3)
implementation(project(":devmenu:data"))
testImplementation(libs.junit.v412) testImplementation(libs.junit.v412)
//testImplementation(libs.junit) //testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.ext.junit)
@@ -25,6 +25,7 @@ import com.ea.easp.EASPHandler
import com.ea.games.nfs13_na.BuildConfig import com.ea.games.nfs13_na.BuildConfig
import com.ea.games.nfs13_na.R import com.ea.games.nfs13_na.R
import com.ea.nimble.ApplicationLifecycle import com.ea.nimble.ApplicationLifecycle
import com.megboyzz.devmenu.data.util.SaveFileObserver
import java.io.BufferedReader import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
@@ -52,12 +53,15 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
private lateinit var gameRenderer: GameRenderer private lateinit var gameRenderer: GameRenderer
lateinit var runLoop: RunLoop lateinit var runLoop: RunLoop
lateinit var gameGLSurfaceView: GameGLSurfaceView lateinit var gameGLSurfaceView: GameGLSurfaceView
// get() = field lateinit var accelerometer: Accelerometer
// private set
private lateinit var accelerometer: Accelerometer
private lateinit var mWakeLock: WakeLock private lateinit var mWakeLock: WakeLock
private lateinit var mAudioManager: AudioManager private lateinit var mAudioManager: AudioManager
private val saveFile = "/data/data/${BuildConfig.APPLICATION_ID}/files/var/nfstr_save.sb"
private val dest = "/sdcard/Android/data/${BuildConfig.APPLICATION_ID}/files/saveTracking"
private val saveFileObserver = SaveFileObserver(saveFile, dest)
companion object { companion object {
const val STATE_RESTORE_CONTEXT = 7 const val STATE_RESTORE_CONTEXT = 7
@@ -92,8 +96,6 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
Log.d(this.localClassName, "Call garbage collector") Log.d(this.localClassName, "Call garbage collector")
System.gc() System.gc()
} }
//fun getGameGLSurfaceView() = gameGLSurfaceView
fun getAccelerometer() = accelerometer
private fun ForceHideVirtualKeyboard() { private fun ForceHideVirtualKeyboard() {
@@ -292,6 +294,9 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
} }
public override fun onCreate(bundle: Bundle?) { public override fun onCreate(bundle: Bundle?) {
saveFileObserver.startWatching()
super.onCreate(bundle) super.onCreate(bundle)
val className = this.localClassName val className = this.localClassName
@@ -346,6 +351,9 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
public override fun onDestroy() { public override fun onDestroy() {
saveFileObserver.stopWatching()
Log.i("Debug", "onDestroy") Log.i("Debug", "onDestroy")
Log.i(this.localClassName, "onDestroy") Log.i(this.localClassName, "onDestroy")
super.onDestroy() super.onDestroy()
@@ -0,0 +1,90 @@
package com.megboyzz.devmenu.data.util
import android.os.FileObserver
import android.util.Log
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.LinkedList
import java.util.Queue
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
abstract class BaseObserver(source: String) : FileObserver(source) {
private val eventQueue : Queue<Int> = LinkedList()
@OptIn(ExperimentalStdlibApi::class)
final override fun onEvent(event: Int, path: String?) {
if(eventQueue.size < 3) eventQueue.add(event)
val e = FileEvent.entries.find { it.value == event }
val fileEvent = e ?: FileEvent.UNKNOWN
Log.i("BaseObserver", "event code = ${event.toHexString()}, FileEvent is $fileEvent")
if(hasLastThreeEvents()) onEvent(fileEvent, path)
}
private fun hasLastThreeEvents() = runCatching {
eventQueue.size == 3 && eventQueue.poll() == OPEN && eventQueue.poll() == ACCESS && eventQueue.poll() == CLOSE_NOWRITE
}.getOrNull() ?: false
abstract fun onEvent(event: FileEvent, path: String?)
protected fun File.list(regex: String = ".") =
this.list { dir, _ -> Regex(regex).matches(dir.absolutePath) }?.asList() ?: listOf()
protected infix fun File.copyToThe(destination: File) = this.copyTo(destination, overwrite = true)
protected fun zipAll(outputFolder: String, filesToCompress: List<String>) {
if(filesToCompress.isEmpty()){
Log.i("BaseObserver", "no files exit!")
return
}
try {
// Проверяем, существует ли выходная папка. Если нет, создаем её.
val outputDir = File(outputFolder)
if (!outputDir.exists()) outputDir.mkdirs()
// Генерируем имя ZIP-архива на основе времени
val timestamp = System.currentTimeMillis()
val zipFileName = "$outputFolder/saves_$timestamp.zip"
val zipOutputStream = ZipOutputStream(FileOutputStream(zipFileName))
for (fileToCompress in filesToCompress) {
// Проверяем, существует ли файл
val inputFile = File(fileToCompress)
if (inputFile.exists()) {
// Создаем объект ZipEntry для каждого файла
val zipEntry = ZipEntry(inputFile.name)
zipOutputStream.putNextEntry(zipEntry)
// Читаем содержимое файла и записываем его в ZIP-архив
val fileInputStream = FileInputStream(inputFile)
val buffer = ByteArray(1024)
var len: Int
while (fileInputStream.read(buffer).also { len = it } > 0) {
zipOutputStream.write(buffer, 0, len)
}
fileInputStream.close()
// Закрываем текущий ZipEntry
zipOutputStream.closeEntry()
} else {
Log.i("SaveFileObserver", "Файл не существует: $fileToCompress")
}
}
// Закрываем ZipOutputStream
zipOutputStream.close()
Log.i("SaveFileObserver", "Архивация завершена. Архив создан: $zipFileName")
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@@ -0,0 +1,22 @@
package com.megboyzz.devmenu.data.util
import android.os.FileObserver
enum class FileEvent(val value: Int) {
ACCESS(FileObserver.ACCESS),
MODIFY(FileObserver.MODIFY),
ATTRIB(FileObserver.ATTRIB),
CLOSE_WRITE(FileObserver.CLOSE_WRITE),
CLOSE_NOWRITE(FileObserver.CLOSE_NOWRITE),
OPEN(FileObserver.OPEN),
MOVED_FROM(FileObserver.MOVED_FROM),
MOVED_TO(FileObserver.MOVED_TO),
CREATE(FileObserver.CREATE),
DELETE(FileObserver.DELETE),
DELETE_SELF(FileObserver.DELETE_SELF),
MOVE_SELF(FileObserver.MOVE_SELF),
UNKNOWN(-1);
override fun toString() = this.name
}
@@ -1,22 +1,52 @@
package com.megboyzz.devmenu.data.util package com.megboyzz.devmenu.data.util
import android.os.FileObserver
import android.util.Log import android.util.Log
import java.io.File import java.io.File
import kotlin.concurrent.thread
class SaveFileObserver( class SaveFileObserver(
private val source: File, private val source: String,
private val destinationFolder: File private val destinationFolder: String
) : FileObserver(source.absolutePath) { ) : BaseObserver(source) {
override fun onEvent(event: Int, path: String?) { private var countSnapshots: Int = 1
if (event and CREATE != 0 || event and MODIFY != 0) {
Log.d("FileObserver", "File created or modified: $source") private val checkList = listOf(
source copyToThe destinationFolder FileEvent.CLOSE_WRITE,
FileEvent.MODIFY,
FileEvent.DELETE,
FileEvent.CREATE,
FileEvent.ACCESS,
FileEvent.OPEN,
FileEvent.CLOSE_NOWRITE
)
init {
val dest = File(destinationFolder)
if(dest.isFile) dest.delete()
if(!dest.exists()) dest.mkdir()
val list = dest.list{
dir, name -> name.endsWith(".sb")
}
list?.forEach { File(dest, it).delete() }
File(source) copyToThe File(destinationFolder, "BASE.sb")
}
override fun onEvent(event: FileEvent, path: String?) {
Log.i("SaveFileObserver", "onEvent $event")
if (event in checkList) {
Log.d("SaveFileObserver", "File created or modified: $source")
File(source) copyToThe File(destinationFolder, "$event-$countSnapshots.sb")
countSnapshots++
} }
} }
private infix fun File.copyToThe(destination: File) = this.copyTo(destination) override fun stopWatching() {
super.stopWatching()
val filesList = File(destinationFolder).list{ _, name -> name.endsWith(".sb") }?.map { it }
if (filesList != null) {
zipAll(destinationFolder, filesList)
}
}
} }