style: format code

This commit is contained in:
13574
2023-09-09 23:46:58 +08:00
parent f0878b4c28
commit 88c51a73d4
22 changed files with 183 additions and 132 deletions

View File

@@ -3,5 +3,5 @@
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@@ -1,37 +1,37 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="@string/app_name"
android:name=".MyApplication"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<provider
android:authorities="com.lifegpc.ehf.ClipboardImageProvider"
android:name=".provider.ClipboardImageProvider"
android:grantUriPermissions="true"
android:exported="false">
android:authorities="com.lifegpc.ehf.ClipboardImageProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_config"/>
android:resource="@xml/file_provider_config" />
</provider>
</application>
</manifest>

View File

@@ -3,8 +3,6 @@ package com.lifegpc.ehf
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.core.content.FileProvider
import androidx.documentfile.provider.DocumentFile
import com.lifegpc.ehf.annotation.ChannelMethod
import com.lifegpc.ehf.data.mmkv.SAFSettings
@@ -13,18 +11,24 @@ import com.lifegpc.ehf.util.MethodChannelUtils
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.FileOutputStream
import java.lang.Exception
class MainActivity : FlutterActivity() {
private val safAuthorizationCode = 0x10086
private var safAuthorizationResult: MethodChannel.Result? = null
private var afterAuthSuccess:(()->Unit)?=null
private var afterAuthSuccess: (() -> Unit)? = null
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannelUtils.registerMethodChannel("lifegpc.eh_downloader_flutter/saf", flutterEngine, this)
MethodChannelUtils.registerMethodChannel("lifegpc.eh_downloader_flutter/clipboard",flutterEngine,ClipboardUtils)
MethodChannelUtils.registerMethodChannel(
"lifegpc.eh_downloader_flutter/saf",
flutterEngine,
this
)
MethodChannelUtils.registerMethodChannel(
"lifegpc.eh_downloader_flutter/clipboard",
flutterEngine,
ClipboardUtils
)
}
@ChannelMethod(responseManually = true)
@@ -36,43 +40,43 @@ class MainActivity : FlutterActivity() {
content: ByteArray
) {
this.safAuthorizationResult = channelResult
if (!checkSafPermission()) {
authSAF(channelResult) {
doWriteFile(filename, dir, mimeType, content)
channelResult.success(null)
}
} else {
doWriteFile(filename, dir, mimeType,content)
if (!checkSafPermission()) {
authSAF(channelResult) {
doWriteFile(filename, dir, mimeType, content)
channelResult.success(null)
}
} else {
doWriteFile(filename, dir, mimeType, content)
channelResult.success(null)
}
}
private fun doWriteFile(filename: String, dir: String, mimeType: String, content: ByteArray) {
var documentDir = DocumentFile.fromTreeUri(this, Uri.parse(SAFSettings.authorizedUri))!!
val pathPart=dir.split('/','\\')
val pathPart = dir.split('/', '\\')
pathPart.forEach {
if (it.isNotEmpty()){
if (it.isNotEmpty()) {
documentDir = documentDir.createDirectory(it)!!
}
}
val filenameWithoutExtension=if (filename.indexOf('.')!=-1){
filename.substring(0,filename.lastIndexOf('.'))
}else{
val filenameWithoutExtension = if (filename.indexOf('.') != -1) {
filename.substring(0, filename.lastIndexOf('.'))
} else {
filename
}
val file=documentDir.createFile(mimeType,filenameWithoutExtension)!!
val uri=file.uri
val file = documentDir.createFile(mimeType, filenameWithoutExtension)!!
val uri = file.uri
contentResolver.openOutputStream(uri)!!.use {
it.write(content)
}
}
private fun authSAF(result: MethodChannel.Result,onSuccess:(()->Unit)?=null) {
private fun authSAF(result: MethodChannel.Result, onSuccess: (() -> Unit)? = null) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, safAuthorizationCode)
safAuthorizationResult = result
this.afterAuthSuccess=onSuccess
this.afterAuthSuccess = onSuccess
}
private fun onSafAuthSuccess(data: Intent) {
@@ -115,7 +119,7 @@ class MainActivity : FlutterActivity() {
safAuthorizationResult?.error("Permission denied", null, null)
safAuthorizationResult = null
}
afterAuthSuccess=null
afterAuthSuccess = null
}
}
}

View File

@@ -3,17 +3,19 @@ package com.lifegpc.ehf
import android.app.Application
import android.content.Context
class MyApplication:Application() {
companion object{
class MyApplication : Application() {
companion object {
@JvmStatic
private var mApplicationContext:Context?=null
private var mApplicationContext: Context? = null
@JvmStatic
@get:JvmName("_applicationContext")
val applicationContext:Context
val applicationContext: Context
get() = mApplicationContext!!
}
override fun onCreate() {
super.onCreate()
mApplicationContext=applicationContext
mApplicationContext = applicationContext
}
}

View File

@@ -9,6 +9,6 @@ package com.lifegpc.ehf.annotation
* 否则,则会将实现方法的返回值返回给 [io.flutter.plugin.common.MethodChannel.Result]
*/
annotation class ChannelMethod(
val methodName:String="",
val responseManually:Boolean=false
val methodName: String = "",
val responseManually: Boolean = false
)

View File

@@ -3,6 +3,6 @@ package com.lifegpc.ehf.data.mmkv
import com.dylanc.mmkv.MMKVOwner
import com.dylanc.mmkv.mmkvString
object SAFSettings:MMKVOwner(mmapID = "SAFSettings") {
object SAFSettings : MMKVOwner(mmapID = "SAFSettings") {
var authorizedUri by mmkvString("")
}

View File

@@ -1,6 +1,5 @@
package com.lifegpc.ehf.provider
import android.net.Uri
import androidx.core.content.FileProvider
class ClipboardImageProvider:FileProvider()
class ClipboardImageProvider : FileProvider()

View File

@@ -10,25 +10,27 @@ import java.io.File
import java.util.UUID
object ClipboardUtils {
private const val AUTHORITY="com.lifegpc.ehf.ClipboardImageProvider"
@ChannelMethod
fun copyImageToClipboard(mimeType:String,byteArray: ByteArray){
val file= saveToImageCache(mimeType, byteArray)
val uri=FileProvider.getUriForFile(MyApplication.applicationContext, AUTHORITY,file)
private const val AUTHORITY = "com.lifegpc.ehf.ClipboardImageProvider"
val cbm=MyApplication.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData=ClipData("image", arrayOf(mimeType),ClipData.Item(uri))
@ChannelMethod
fun copyImageToClipboard(mimeType: String, byteArray: ByteArray) {
val file = saveToImageCache(mimeType, byteArray)
val uri = FileProvider.getUriForFile(MyApplication.applicationContext, AUTHORITY, file)
val cbm =
MyApplication.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData("image", arrayOf(mimeType), ClipData.Item(uri))
cbm.setPrimaryClip(clipData)
}
private fun saveToImageCache(mimeType:String,byteArray: ByteArray):File{
val dir=File(MyApplication.applicationContext.filesDir,"images")
if (!dir.exists()){
private fun saveToImageCache(mimeType: String, byteArray: ByteArray): File {
val dir = File(MyApplication.applicationContext.filesDir, "images")
if (!dir.exists()) {
dir.mkdirs()
}
val name=UUID.randomUUID().toString()
val name = UUID.randomUUID().toString()
val file=File(dir,"$name.${mimeTypeToExtName(mimeType)}")
val file = File(dir, "$name.${mimeTypeToExtName(mimeType)}")
file.outputStream().use {
it.write(byteArray)
@@ -37,10 +39,10 @@ object ClipboardUtils {
return file
}
private fun mimeTypeToExtName(mimeType: String)=when(mimeType){
"image/png"->"png"
"image/jpeg"->"png"
"image/gif"->"gif"
else->throw IllegalArgumentException("$mimeType is not supported")
private fun mimeTypeToExtName(mimeType: String) = when (mimeType) {
"image/png" -> "png"
"image/jpeg" -> "png"
"image/gif" -> "gif"
else -> throw IllegalArgumentException("$mimeType is not supported")
}
}

View File

@@ -4,69 +4,84 @@ import android.util.Log
import com.lifegpc.ehf.annotation.ChannelMethod
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.lang.Exception
import java.lang.reflect.Method
import java.lang.reflect.Modifier
object MethodChannelUtils {
@JvmStatic
fun registerMethodChannel(channelName: String, flutterEngine: FlutterEngine, obj: Any,ignoreNotImplemented:Boolean=true) {
fun registerMethodChannel(
channelName: String,
flutterEngine: FlutterEngine,
obj: Any,
ignoreNotImplemented: Boolean = true
) {
val methodsMapping = mutableMapOf<String, Method>()
val methods = obj::class.java.declaredMethods
methods.forEach {
val annotation = it.getAnnotation(ChannelMethod::class.java) ?: return@forEach
val methodName = annotation.methodName.takeIf(String::isNotBlank) ?: it.name
methodsMapping[methodName]=it
methodsMapping[methodName] = it
}
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName).setMethodCallHandler { call, result ->
val invokeMethodName=call.method
val targetMethod=methodsMapping[invokeMethodName]
if (targetMethod==null){
Log.w("MethodChannel","$channelName/$invokeMethodName not implemented.")
if (!ignoreNotImplemented){
MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
channelName
).setMethodCallHandler { call, result ->
val invokeMethodName = call.method
val targetMethod = methodsMapping[invokeMethodName]
if (targetMethod == null) {
Log.w("MethodChannel", "$channelName/$invokeMethodName not implemented.")
if (!ignoreNotImplemented) {
result.notImplemented()
}else{
result.error("Not implemented",null,null)
} else {
result.error("Not implemented", null, null)
}
return@setMethodCallHandler
}else{
val argv=call.arguments?.takeIf { it is List<*> } as List<*>? ?:return@setMethodCallHandler result.error("Argument must be List",null,null)
val argTypes=targetMethod.parameterTypes
val targetArgc=argTypes.size
} else {
val argv = call.arguments?.takeIf { it is List<*> } as List<*>?
?: return@setMethodCallHandler result.error("Argument must be List", null, null)
val argTypes = targetMethod.parameterTypes
val targetArgc = argTypes.size
val invokeTargetObject=if (Modifier.isStatic(targetMethod.modifiers)) null else obj
targetMethod.isAccessible=true
val invokeTargetObject =
if (Modifier.isStatic(targetMethod.modifiers)) null else obj
targetMethod.isAccessible = true
if (targetArgc==argv.size){
if (targetArgc == argv.size) {
try {
val res=targetMethod.invoke(invokeTargetObject,*(argv.toTypedArray()))
if (res is Unit){
val res = targetMethod.invoke(invokeTargetObject, *(argv.toTypedArray()))
if (res is Unit) {
result.success(null)
}else{
} else {
result.success(res)
}
}catch (e:Exception){
} catch (e: Exception) {
e.printStackTrace()
result.error("Error",e.toString(),e.stackTraceToString())
result.error("Error", e.toString(), e.stackTraceToString())
}
}else if (targetArgc==argv.size+1&&argTypes[0]==MethodChannel.Result::class.java){
} else if (targetArgc == argv.size + 1 && argTypes[0] == MethodChannel.Result::class.java) {
try {
val responseManually=targetMethod.getAnnotation(ChannelMethod::class.java)!!.responseManually
val res=targetMethod.invoke(invokeTargetObject,result,*(argv.toTypedArray()))
if (!responseManually){
if (res is Unit){
val responseManually =
targetMethod.getAnnotation(ChannelMethod::class.java)!!.responseManually
val res =
targetMethod.invoke(invokeTargetObject, result, *(argv.toTypedArray()))
if (!responseManually) {
if (res is Unit) {
result.success(null)
}else{
} else {
result.success(res)
}
}
}catch (e:Exception){
} catch (e: Exception) {
e.printStackTrace()
result.error("Error",e.toString(),e.stackTraceToString())
result.error("Error", e.toString(), e.stackTraceToString())
}
}else{
result.error("Error","Parameter count error, required: $targetArgc, found: $argv",null)
} else {
result.error(
"Error",
"Parameter count error, required: $targetArgc, found: $argv",
null
)
}
}
}

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<?xml version="1.0" encoding="utf-8"?><!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<?xml version="1.0" encoding="utf-8"?><!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />

View File

@@ -2,5 +2,5 @@
<paths>
<files-path
name="images"
path="images"/>
path="images" />
</paths>

View File

@@ -3,5 +3,5 @@
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>