* fix(android): use app filesDir for persistence and SAF log export Honor devices reject writes under /data/local/tmp, which caused PreferencesStore to fall back to openless_prefs_fallback.json and settings saves to fail. Initialize JNI storage roots before Coordinator and file logging, route logs to files/logs/openless.log, and export via ContentResolver for SAF content:// URIs. * fix(android): guard StylePack empty asset_root and Android-only coord logs Reject persisting style pack icons when asset_root is empty to avoid writing under cwd; no-op cleanup on empty root. Limit Coordinator persistence degrade log suffix to Android only. Add unit test. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
38 lines
1.1 KiB
Kotlin
38 lines
1.1 KiB
Kotlin
package com.openless.app
|
|
|
|
import android.content.Context
|
|
import android.net.Uri
|
|
import android.util.Log
|
|
import androidx.annotation.Keep
|
|
|
|
/**
|
|
* Writes bytes to a SAF content:// URI via ContentResolver.
|
|
*
|
|
* Prefer this over tauri-plugin-fs for exports: fs detaches the FD early and
|
|
* some providers finalize a 0-byte file before Rust finishes writing.
|
|
*/
|
|
@Keep
|
|
object OpenLessContentWriter {
|
|
private const val TAG = "OpenLessContentWriter"
|
|
|
|
@Keep
|
|
@JvmStatic
|
|
fun writeBytes(context: Context, uriString: String, bytes: ByteArray): Boolean {
|
|
return try {
|
|
val uri = Uri.parse(uriString)
|
|
context.contentResolver.openOutputStream(uri)?.use { output ->
|
|
output.write(bytes)
|
|
output.flush()
|
|
} ?: run {
|
|
Log.w(TAG, "openOutputStream returned null for $uriString")
|
|
return false
|
|
}
|
|
Log.i(TAG, "wrote ${bytes.size} bytes to $uriString")
|
|
true
|
|
} catch (error: Throwable) {
|
|
Log.e(TAG, "failed to write $uriString", error)
|
|
false
|
|
}
|
|
}
|
|
}
|