android: stricter IO usage
This commit is contained in:
parent
888c5e567f
commit
9b90c7ba84
7 changed files with 76 additions and 54 deletions
|
@ -31,6 +31,18 @@ class MainActivity : FlutterActivity() {
|
|||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
||||
// StrictMode.setThreadPolicy(
|
||||
// StrictMode.ThreadPolicy.Builder()
|
||||
// .detectAll()
|
||||
// .penaltyLog()
|
||||
// .build()
|
||||
// )
|
||||
// StrictMode.setVmPolicy(
|
||||
// StrictMode.VmPolicy.Builder()
|
||||
// .detectAll()
|
||||
// .penaltyLog()
|
||||
// .build()
|
||||
// )
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val messenger = flutterEngine!!.dartExecutor.binaryMessenger
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.util.*
|
|||
class DebugHandler(private val context: Context) : MethodCallHandler {
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"getContextDirs" -> result.success(getContextDirs())
|
||||
"getContextDirs" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getContextDirs) }
|
||||
"getEnv" -> result.success(System.getenv())
|
||||
"getBitmapFactoryInfo" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getBitmapFactoryInfo) }
|
||||
"getContentResolverMetadata" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getContentResolverMetadata) }
|
||||
|
@ -48,24 +48,28 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getContextDirs() = hashMapOf(
|
||||
"cacheDir" to context.cacheDir,
|
||||
"filesDir" to context.filesDir,
|
||||
"obbDir" to context.obbDir,
|
||||
"externalCacheDir" to context.externalCacheDir,
|
||||
).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
putAll(
|
||||
hashMapOf(
|
||||
"codeCacheDir" to context.codeCacheDir,
|
||||
"noBackupFilesDir" to context.noBackupFilesDir,
|
||||
private fun getContextDirs(@Suppress("UNUSED_PARAMETER") call: MethodCall, result: MethodChannel.Result) {
|
||||
val dirs = hashMapOf(
|
||||
"cacheDir" to context.cacheDir,
|
||||
"filesDir" to context.filesDir,
|
||||
"obbDir" to context.obbDir,
|
||||
"externalCacheDir" to context.externalCacheDir,
|
||||
).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
putAll(
|
||||
hashMapOf(
|
||||
"codeCacheDir" to context.codeCacheDir,
|
||||
"noBackupFilesDir" to context.noBackupFilesDir,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
put("dataDir", context.dataDir)
|
||||
}
|
||||
}.mapValues { it.value?.path }
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
put("dataDir", context.dataDir)
|
||||
}
|
||||
}.mapValues { it.value?.path }
|
||||
|
||||
result.success(dirs)
|
||||
}
|
||||
|
||||
private fun getBitmapFactoryInfo(call: MethodCall, result: MethodChannel.Result) {
|
||||
val uri = call.argument<String>("uri")?.let { Uri.parse(it) }
|
||||
|
|
|
@ -9,11 +9,14 @@ import deckers.thibault.aves.utils.LogUtils
|
|||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class GlobalSearchHandler(private val context: Activity) : MethodCallHandler {
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"registerCallback" -> safe(call, result, ::registerCallback)
|
||||
"registerCallback" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::registerCallback) }
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +28,6 @@ class GlobalSearchHandler(private val context: Activity) : MethodCallHandler {
|
|||
return
|
||||
}
|
||||
|
||||
Log.i(LOG_TAG, "register global search callback")
|
||||
context.getSharedPreferences(SearchSuggestionsProvider.SHARED_PREFERENCES_KEY, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putLong(SearchSuggestionsProvider.CALLBACK_HANDLE_KEY, callbackHandle)
|
||||
|
|
|
@ -23,13 +23,13 @@ import java.util.*
|
|||
class StorageHandler(private val context: Context) : MethodCallHandler {
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"getStorageVolumes" -> safe(call, result, ::getStorageVolumes)
|
||||
"getFreeSpace" -> safe(call, result, ::getFreeSpace)
|
||||
"getGrantedDirectories" -> safe(call, result, ::getGrantedDirectories)
|
||||
"getInaccessibleDirectories" -> safe(call, result, ::getInaccessibleDirectories)
|
||||
"getRestrictedDirectories" -> safe(call, result, ::getRestrictedDirectories)
|
||||
"getStorageVolumes" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getStorageVolumes) }
|
||||
"getFreeSpace" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getFreeSpace) }
|
||||
"getGrantedDirectories" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getGrantedDirectories) }
|
||||
"getInaccessibleDirectories" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getInaccessibleDirectories) }
|
||||
"getRestrictedDirectories" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::getRestrictedDirectories) }
|
||||
"revokeDirectoryAccess" -> safe(call, result, ::revokeDirectoryAccess)
|
||||
"deleteEmptyDirectories" -> safe(call, result, ::deleteEmptyDirectories)
|
||||
"deleteEmptyDirectories" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::deleteEmptyDirectories) }
|
||||
"scanFile" -> GlobalScope.launch(Dispatchers.IO) { safe(call, result, ::scanFile) }
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
|||
private fun getStorageVolumes(@Suppress("UNUSED_PARAMETER") call: MethodCall, result: MethodChannel.Result) {
|
||||
val volumes = ArrayList<Map<String, Any>>()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val sm = context.getSystemService(StorageManager::class.java)
|
||||
val sm = context.getSystemService(Context.STORAGE_SERVICE) as? StorageManager
|
||||
if (sm != null) {
|
||||
for (volumePath in getVolumePaths(context)) {
|
||||
try {
|
||||
|
|
|
@ -39,7 +39,7 @@ class StorageAccessStreamHandler(private val activity: Activity, arguments: Any?
|
|||
handler = Handler(Looper.getMainLooper())
|
||||
|
||||
when (op) {
|
||||
"requestVolumeAccess" -> requestVolumeAccess()
|
||||
"requestVolumeAccess" -> GlobalScope.launch(Dispatchers.IO) { requestVolumeAccess() }
|
||||
"createFile" -> GlobalScope.launch(Dispatchers.IO) { createFile() }
|
||||
"openFile" -> GlobalScope.launch(Dispatchers.IO) { openFile() }
|
||||
"selectDirectory" -> GlobalScope.launch(Dispatchers.IO) { selectDirectory() }
|
||||
|
@ -83,18 +83,20 @@ class StorageAccessStreamHandler(private val activity: Activity, arguments: Any?
|
|||
putExtra(Intent.EXTRA_TITLE, name)
|
||||
}
|
||||
MainActivity.pendingResultHandlers[MainActivity.CREATE_FILE_REQUEST] = PendingResultHandler(null, { uri ->
|
||||
try {
|
||||
activity.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
output as FileOutputStream
|
||||
// truncate is necessary when overwriting a longer file
|
||||
output.channel.truncate(0)
|
||||
output.write(bytes)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
activity.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
output as FileOutputStream
|
||||
// truncate is necessary when overwriting a longer file
|
||||
output.channel.truncate(0)
|
||||
output.write(bytes)
|
||||
}
|
||||
success(true)
|
||||
} catch (e: Exception) {
|
||||
error("createFile-write", "failed to write file at uri=$uri", e.message)
|
||||
}
|
||||
success(true)
|
||||
} catch (e: Exception) {
|
||||
error("createFile-write", "failed to write file at uri=$uri", e.message)
|
||||
endOfStream()
|
||||
}
|
||||
endOfStream()
|
||||
}, {
|
||||
success(null)
|
||||
endOfStream()
|
||||
|
@ -115,13 +117,15 @@ class StorageAccessStreamHandler(private val activity: Activity, arguments: Any?
|
|||
type = mimeType
|
||||
}
|
||||
MainActivity.pendingResultHandlers[MainActivity.OPEN_FILE_REQUEST] = PendingResultHandler(null, { uri ->
|
||||
activity.contentResolver.openInputStream(uri)?.use { input ->
|
||||
val buffer = ByteArray(BUFFER_SIZE)
|
||||
var len: Int
|
||||
while (input.read(buffer).also { len = it } != -1) {
|
||||
success(buffer.copyOf(len))
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
activity.contentResolver.openInputStream(uri)?.use { input ->
|
||||
val buffer = ByteArray(BUFFER_SIZE)
|
||||
var len: Int
|
||||
while (input.read(buffer).also { len = it } != -1) {
|
||||
success(buffer.copyOf(len))
|
||||
}
|
||||
endOfStream()
|
||||
}
|
||||
endOfStream()
|
||||
}
|
||||
}, {
|
||||
success(ByteArray(0))
|
||||
|
|
|
@ -25,7 +25,7 @@ object PermissionManager {
|
|||
|
||||
var intent: Intent? = null
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
val sm = activity.getSystemService(StorageManager::class.java)
|
||||
val sm = activity.getSystemService(Context.STORAGE_SERVICE) as? StorageManager
|
||||
intent = sm?.getStorageVolume(File(path))?.createOpenDocumentTreeIntent()
|
||||
}
|
||||
|
||||
|
|
|
@ -187,14 +187,13 @@ object StorageUtils {
|
|||
// /storage/10F9-3F13/Pictures/ -> 10F9-3F13
|
||||
private fun getVolumeUuidForTreeUri(context: Context, anyPath: String): String? {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
context.getSystemService(StorageManager::class.java)?.let { sm ->
|
||||
sm.getStorageVolume(File(anyPath))?.let { volume ->
|
||||
if (volume.isPrimary) {
|
||||
return "primary"
|
||||
}
|
||||
volume.uuid?.let { uuid ->
|
||||
return uuid.uppercase(Locale.ROOT)
|
||||
}
|
||||
val sm = context.getSystemService(Context.STORAGE_SERVICE) as? StorageManager
|
||||
sm?.getStorageVolume(File(anyPath))?.let { volume ->
|
||||
if (volume.isPrimary) {
|
||||
return "primary"
|
||||
}
|
||||
volume.uuid?.let { uuid ->
|
||||
return uuid.uppercase(Locale.ROOT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -222,7 +221,8 @@ object StorageUtils {
|
|||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
context.getSystemService(StorageManager::class.java)?.let { sm ->
|
||||
val sm = context.getSystemService(Context.STORAGE_SERVICE) as? StorageManager
|
||||
if (sm != null) {
|
||||
for (volumePath in getVolumePaths(context)) {
|
||||
try {
|
||||
val volume = sm.getStorageVolume(File(volumePath))
|
||||
|
|
Loading…
Reference in a new issue