This commit is contained in:
2024-11-17 16:01:34 +08:00
commit 7d68ed0f6c
250 changed files with 8930 additions and 0 deletions

70
android/build.gradle Normal file
View File

@ -0,0 +1,70 @@
group 'me.yohom.foundation_fluttify'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = "1.8.22"
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.1.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
if (project.android.hasProperty("namespace")) {
namespace = "me.yohom.foundation_fluttify"
}
compileSdk = 34
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
sourceSets {
main.java.srcDirs += "src/main/kotlin"
test.java.srcDirs += "src/test/kotlin"
}
defaultConfig {
minSdk = 21
}
dependencies {
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.mockito:mockito-core:5.0.0")
}
testOptions {
unitTests.all {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen {false}
showStandardStreams = true
}
}
}
}

View File

@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

1
android/settings.gradle Normal file
View File

@ -0,0 +1 @@
rootProject.name = 'foundation_fluttify'

View File

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="me.yohom.foundation_fluttify">
<application>
<receiver android:name=".FluttifyBroadcastReceiver" />
</application>
</manifest>

View File

@ -0,0 +1,82 @@
package me.yohom.foundation_fluttify.core;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.StandardMessageCodec;
import me.yohom.foundation_fluttify.FoundationFluttifyPluginKt;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.*;
public class FluttifyMessageCodec extends StandardMessageCodec {
private static final Charset UTF8 = Charset.forName("UTF8");
// 总体逻辑, 先尝试使用标准编解码进行处理, 如果发生异常再使用自定义的编解码处理, 再不行就只能抛异常了
private static final byte ARRAY = 125;
private static final byte ENUM = 126;
private static final byte REF = 127;
@Override
protected void writeValue(@NonNull ByteArrayOutputStream stream, @NonNull Object value) {
try {
super.writeValue(stream, value);
} catch (IllegalArgumentException e) {
// 对象数组转换
if (value instanceof Object[]) {
stream.write(ARRAY);
Object[] array = (Object[]) value;
writeSize(stream, array.length);
for (Object item : array) {
writeValue(stream, item);
}
}
// 枚举值传索引
else if (value instanceof Enum) {
stream.write(ENUM);
writeInt(stream, ((Enum<?>) value).ordinal());
} else {
final String refId = value.getClass().getName() + ":" + System.identityHashCode(value);
// 放入HEAP
FoundationFluttifyPluginKt.getHEAP().put(refId, value);
stream.write(REF);
writeBytes(stream, refId.getBytes(UTF8));
}
}
}
@Nullable
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
Object result;
try {
result = super.readValueOfType(type, buffer);
} catch (IllegalArgumentException e) {
switch (type) {
case ARRAY:
final int size = readSize(buffer);
final List<Object> list = new ArrayList<>(size);
int i = 0;
while (i < size) {
list.add(readValue(buffer));
i++;
}
result = list.toArray();
break;
case ENUM:
result = buffer.getInt();
break;
case REF:
final byte[] bytes = readBytes(buffer);
result = FoundationFluttifyPluginKt.getHEAP().get(new String(bytes, UTF8));
break;
default:
result = null;
}
}
return result;
}
}

View File

@ -0,0 +1,157 @@
package me.yohom.foundation_fluttify
import android.app.Activity
import android.content.Context
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.platform.PlatformViewRegistry
import me.yohom.foundation_fluttify.android.app.ActivityHandler
import me.yohom.foundation_fluttify.android.app.ApplicationHandler
import me.yohom.foundation_fluttify.android.app.NotificationHandler
import me.yohom.foundation_fluttify.android.app.PendingIntentHandler
import me.yohom.foundation_fluttify.android.content.BroadcastReceiverHandler
import me.yohom.foundation_fluttify.android.content.ContextHandler
import me.yohom.foundation_fluttify.android.content.IntentFilterHandler
import me.yohom.foundation_fluttify.android.content.IntentHandler
import me.yohom.foundation_fluttify.android.graphics.BitmapHandler
import me.yohom.foundation_fluttify.android.graphics.PointHandler
import me.yohom.foundation_fluttify.android.location.LocationHandler
import me.yohom.foundation_fluttify.android.os.BundleHandler
import me.yohom.foundation_fluttify.android.util.PairHandler
import me.yohom.foundation_fluttify.android.view.SurfaceHolderHandler
import me.yohom.foundation_fluttify.android.view.SurfaceViewHandler
import me.yohom.foundation_fluttify.android.view.ViewGroupHandler
import me.yohom.foundation_fluttify.android.view.ViewHandler
import me.yohom.foundation_fluttify.android.widget.ImageViewHandler
import me.yohom.foundation_fluttify.core.FluttifyMessageCodec
import me.yohom.foundation_fluttify.core.PlatformService
import me.yohom.foundation_fluttify.java.io.FileHandler
import me.yohom.foundation_fluttify.platform_view.android_opengl_GLSurfaceViewFactory
import me.yohom.foundation_fluttify.platform_view.android_view_SurfaceViewFactory
import me.yohom.foundation_fluttify.platform_view.android_widget_FrameLayoutFactory
// The stack that exists on the Dart side for a method call is enabled only when the MethodChannel passing parameters are limited
val STACK = mutableMapOf<String, Any>()
// Container for Dart side random access objects
val HEAP = mutableMapOf<String, Any>()
// whether enable log or not
var enableLog: Boolean = true
// method channel for foundation
lateinit var gMethodChannel: MethodChannel
class FoundationFluttifyPlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
private var applicationContext: Context? = null
private var activity: Activity? = null
private var activityBinding: ActivityPluginBinding? = null
private var pluginBinding: FlutterPlugin.FlutterPluginBinding? = null
private var registrar: Registrar? = null
private var platformViewRegistry: PlatformViewRegistry? = null
private var binaryMessenger: BinaryMessenger? = null
companion object {
@JvmStatic
fun registerWith(registrar: Registrar) {
val plugin = FoundationFluttifyPlugin()
plugin.registrar = registrar
plugin.platformViewRegistry = registrar.platformViewRegistry()
plugin.binaryMessenger = registrar.messenger()
plugin.activity = registrar.activity()
plugin.applicationContext = registrar.activity()?.applicationContext
plugin.platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.view.SurfaceView", android_view_SurfaceViewFactory(registrar.messenger()))
plugin.platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.widget.FrameLayout", android_widget_FrameLayoutFactory())
plugin.platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.opengl.GLSurfaceView", android_opengl_GLSurfaceViewFactory())
gMethodChannel = MethodChannel(
registrar.messenger(),
"com.fluttify/foundation_method",
StandardMethodCodec(FluttifyMessageCodec())
)
gMethodChannel.setMethodCallHandler(plugin)
}
}
override fun onMethodCall(methodCall: MethodCall, methodResult: Result) {
val rawArgs = methodCall.arguments ?: mapOf<String, Any>()
methodCall.method.run {
when {
startsWith("android.app.Application::") -> ApplicationHandler(methodCall.method, rawArgs, methodResult, applicationContext)
startsWith("android.app.Activity::") -> ActivityHandler(methodCall.method, rawArgs, methodResult, activity)
startsWith("android.app.PendingIntent::") -> PendingIntentHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.app.Notification::") -> NotificationHandler(methodCall.method, rawArgs, methodResult, activity)
startsWith("android.os.Bundle::") -> BundleHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.content.Intent::") -> IntentHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.content.Context::") -> ContextHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.content.BroadcastReceiver::") -> BroadcastReceiverHandler(methodCall.method, rawArgs, registrar?.messenger(), methodResult)
startsWith("android.content.IntentFilter::") -> IntentFilterHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.graphics.Bitmap::") -> BitmapHandler(methodCall.method, rawArgs, methodResult, activity)
startsWith("android.graphics.Point::") -> PointHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.location.Location::") -> LocationHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.util.Pair::") -> PairHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.view.View::") -> ViewHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.view.SurfaceView::") -> SurfaceViewHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.view.SurfaceHolder::") -> SurfaceHolderHandler(binaryMessenger, methodCall.method, rawArgs, methodResult)
startsWith("android.view.ViewGroup::") -> ViewGroupHandler(methodCall.method, rawArgs, methodResult)
startsWith("android.widget.ImageView::") -> ImageViewHandler(methodCall.method, rawArgs, methodResult, activity)
startsWith("java.io.File::") -> FileHandler(methodCall.method, rawArgs, methodResult)
startsWith("PlatformService::") -> PlatformService(methodCall.method, rawArgs as Map<String, Any>, methodResult, activityBinding, pluginBinding, registrar)
else -> methodResult.notImplemented()
}
}
}
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
applicationContext = binding.applicationContext
pluginBinding = binding
platformViewRegistry = binding.platformViewRegistry
binaryMessenger = binding.binaryMessenger
gMethodChannel = MethodChannel(
binding.binaryMessenger,
"com.fluttify/foundation_method",
StandardMethodCodec(FluttifyMessageCodec())
)
gMethodChannel.setMethodCallHandler(this)
}
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
pluginBinding = null
activity = null
activityBinding = null
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity
activityBinding = binding
platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.view.SurfaceView", android_view_SurfaceViewFactory(binaryMessenger))
platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.widget.FrameLayout", android_widget_FrameLayoutFactory())
platformViewRegistry?.registerViewFactory("me.yohom/foundation_fluttify/android.opengl.GLSurfaceView", android_opengl_GLSurfaceViewFactory())
}
override fun onDetachedFromActivity() {
activity = null
activityBinding = null
}
override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
activity = binding.activity
activityBinding = binding
}
override fun onDetachedFromActivityForConfigChanges() {
activity = null
activityBinding = null
}
}

View File

@ -0,0 +1,17 @@
package me.yohom.foundation_fluttify.android.app
import android.app.Activity
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
fun ActivityHandler(method: String, args: Any, methodResult: MethodChannel.Result, context: Activity?) {
when (method) {
"android.app.Activity::getIntent" -> {
methodResult.success(args.__this__<Activity>().intent)
}
"android.app.Activity::get" -> {
methodResult.success(context)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,13 @@
package me.yohom.foundation_fluttify.android.app
import android.content.Context
import io.flutter.plugin.common.MethodChannel
fun ApplicationHandler(method: String, args: Any, methodResult: MethodChannel.Result, context: Context?) {
when (method) {
"android.app.Application::get" -> {
methodResult.success(context)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,65 @@
package me.yohom.foundation_fluttify.android.app
import android.app.Activity
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.Color
import android.os.Build
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.HEAP
import me.yohom.foundation_fluttify.enableLog
fun NotificationHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result, activity: Activity?) {
when (method) {
"android.app.Notification::create" -> {
val args = rawArgs as Map<String, Any>
if (activity == null) {
methodResult.error("activity cannot be null", "activity cannot be null", "activity cannot be null")
} else {
val contentTitle = args["contentTitle"] as String
val contentText = args["contentText"] as String
val `when` = args["when"] as Long
val channelId = args["channelId"] as String
val channelName = args["channelName"] as String
val enableLights = args["enableLights"] as Boolean
val showBadge = args["showBadge"] as Boolean
if (enableLog) {
android.util.Log.d("Notification create: ", "contentTitle: $contentTitle, contentText: $contentText, when: $`when`, channelId: $channelId, channelName: $channelName, enableLights: $enableLights, showBadge: $showBadge")
}
val notificationManager: NotificationManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Android O上对Notification进行了修改如果设置的targetSDKVersion>=26建议使用此种方式创建通知栏
val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= 26) {
val notificationChannel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT)
.apply {
enableLights(enableLights) //是否在桌面icon右上角展示小圆点
lightColor = Color.BLUE //小圆点颜色
setShowBadge(showBadge) //是否在久按桌面图标时显示此渠道的通知
}
notificationManager.createNotificationChannel(notificationChannel)
Notification.Builder(activity.applicationContext, channelId)
} else {
Notification.Builder(activity.applicationContext)
}
// TODO: 从flutter传icon数据过来
val iconId = activity.resources.getIdentifier("ic_launcher", "mipmap", activity.packageName)
builder.setSmallIcon(iconId)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setWhen(`when`)
val notification = builder.build()
methodResult.success(notification)
}
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,9 @@
package me.yohom.foundation_fluttify.android.app
import io.flutter.plugin.common.MethodChannel
fun PendingIntentHandler(method: String, args: Any, methodResult: MethodChannel.Result) {
when (method) {
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,29 @@
package me.yohom.foundation_fluttify.android.content
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.HEAP
fun BroadcastReceiverHandler(method: String, rawArgs: Any, binaryMessenger: BinaryMessenger?, methodResult: MethodChannel.Result) {
when (method) {
"android.content.BroadcastReceiver::create" -> {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (binaryMessenger != null) {
MethodChannel(binaryMessenger, "android.content.BroadcastReceiver::create::Callback")
.invokeMethod(
"Callback::android.content.BroadcastReceiver::onReceive",
mapOf("intent" to intent)
)
}
}
}
methodResult.success(receiver)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,24 @@
package me.yohom.foundation_fluttify.android.content
import android.content.BroadcastReceiver
import android.content.Context
import android.content.IntentFilter
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun ContextHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.content.Context::registerReceiver" -> {
val broadcastReceiver = rawArgs["broadcastReceiver"] as BroadcastReceiver
val intentFilter = rawArgs["intentFilter"] as IntentFilter
val context: Context = rawArgs.__this__()
val intent = context.registerReceiver(broadcastReceiver, intentFilter)
methodResult.success(intent)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,18 @@
package me.yohom.foundation_fluttify.android.content
import android.content.IntentFilter
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.get
fun IntentFilterHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.content.IntentFilter::create" -> {
val action = rawArgs["action"] as String
val intentFilter = IntentFilter(action)
methodResult.success(intentFilter)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,31 @@
package me.yohom.foundation_fluttify.android.content
import android.content.Intent
import android.os.Bundle
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
fun IntentHandler(method: String, args: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.content.Intent::getBundle" -> {
val intent: Intent = args.__this__()
val bundle = intent.extras ?: Bundle.EMPTY
val result: MutableMap<String, java.io.Serializable?> = mutableMapOf()
for (key in bundle.keySet()) {
result[key] = bundle.getSerializable(key)
}
methodResult.success(result)
}
"android.content.Intent::getAction" -> {
val intent: Intent = args.__this__()
val action = intent.action
methodResult.success(action)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,57 @@
package me.yohom.foundation_fluttify.android.graphics
import android.app.Activity
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
import java.io.ByteArrayOutputStream
fun BitmapHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result, activity: Activity?) {
when (method) {
"android.graphics.Bitmap::create" -> {
val bitmapBytes = rawArgs["bitmapBytes"] as ByteArray
val bitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.size)
methodResult.success(bitmap)
}
"android.graphics.Bitmap::createWithDrawable" -> {
val drawableId = rawArgs["drawableId"] as Int
if (activity != null) {
val bitmap = BitmapFactory.decodeResource(activity.resources, drawableId)
methodResult.success(bitmap)
} else {
methodResult.error("Activity不能为null", "Activity不能为null", "Activity不能为null")
}
}
"android.graphics.Bitmap::create_batch" -> {
val typedArgs = rawArgs as List<Map<String, ByteArray>>
val bitmapBytesBatch = typedArgs.map { it["bitmapBytes"] as ByteArray }
val resultBatch = bitmapBytesBatch
.map { BitmapFactory.decodeByteArray(it, 0, it.size) }
methodResult.success(resultBatch)
}
"android.graphics.Bitmap::getData" -> {
val bitmap = rawArgs["__this__"] as Bitmap
val outputStream = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
methodResult.success(outputStream.toByteArray())
}
"android.graphics.Bitmap::recycle" -> {
val bitmap: Bitmap = rawArgs.__this__()
bitmap.recycle()
methodResult.success("success")
}
"android.graphics.Bitmap::isRecycled" -> {
val bitmap: Bitmap = rawArgs.__this__()
methodResult.success(bitmap.isRecycled)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,29 @@
package me.yohom.foundation_fluttify.android.graphics
import android.graphics.Point
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun PointHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.graphics.Point::create" -> {
val x = rawArgs["x"] as Int
val y = rawArgs["y"] as Int
val point = Point(x, y)
methodResult.success(point)
}
"android.graphics.Point::getX" -> {
val point: Point = rawArgs.__this__()
methodResult.success(point.x)
}
"android.graphics.Point::getY" -> {
val point: Point = rawArgs.__this__()
methodResult.success(point.y)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,102 @@
package me.yohom.foundation_fluttify.android.location
import android.location.Location
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun LocationHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.location.Location::create" -> {
val provider = rawArgs["provider"] as String
val location = Location(provider)
methodResult.success(location)
}
"android.location.Location::getLatitude" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.latitude)
}
"android.location.Location::getLongitude" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.longitude)
}
"android.location.Location::getBearing" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.bearing)
}
"android.location.Location::getAltitude" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.altitude)
}
"android.location.Location::getAccuracy" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.accuracy)
}
"android.location.Location::getSpeed" -> {
val location: Location = rawArgs.__this__()
methodResult.success(location.speed)
}
"android.location.Location::setLatitude" -> {
val latitude = rawArgs["latitude"] as Double
val location: Location = rawArgs.__this__()
location.latitude = latitude
methodResult.success("success")
}
"android.location.Location::setLongitude" -> {
val longitude = rawArgs["longitude"] as Double
val location: Location = rawArgs.__this__()
location.longitude = longitude
methodResult.success("success")
}
"android.location.Location::setBearing" -> {
val bearing = rawArgs["bearing"] as Double
val location: Location = rawArgs.__this__()
location.bearing = bearing.toFloat()
methodResult.success("success")
}
"android.location.Location::setAltitude" -> {
val altitude = rawArgs["altitude"] as Double
val location: Location = rawArgs.__this__()
location.altitude = altitude
methodResult.success("success")
}
"android.location.Location::setAccuracy" -> {
val accuracy = rawArgs["accuracy"] as Double
val location: Location = rawArgs.__this__()
location.accuracy = accuracy.toFloat()
methodResult.success("success")
}
"android.location.Location::setSpeed" -> {
val speed = rawArgs["speed"] as Double
val location: Location = rawArgs.__this__()
location.speed = speed.toFloat()
methodResult.success("success")
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,75 @@
package me.yohom.foundation_fluttify.android.os
import android.os.Bundle
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun BundleHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.os.Bundle::create" -> {
val target = Bundle()
methodResult.success(target)
}
"android.os.Bundle::putString" -> {
val key = rawArgs["key"] as String
val value = rawArgs["value"] as String
val bundle: Bundle = rawArgs.__this__()
bundle.putString(key, value)
methodResult.success("success")
}
"android.os.Bundle::putInt" -> {
val key = rawArgs["key"] as String
val value = rawArgs["value"] as Int
val bundle: Bundle = rawArgs.__this__()
bundle.putInt(key, value)
methodResult.success("success")
}
"android.os.Bundle::getString" -> {
val key = rawArgs["key"] as String
val bundle: Bundle = rawArgs.__this__()
methodResult.success(bundle.getString(key))
}
"android.os.Bundle::getInt" -> {
val key = rawArgs["key"] as String
val bundle: Bundle = rawArgs.__this__()
methodResult.success(bundle.getInt(key))
}
"android.os.Bundle::getFloat" -> {
val key = rawArgs["key"] as String
val bundle: Bundle = rawArgs.__this__()
methodResult.success(bundle.getFloat(key))
}
"android.os.Bundle::getDouble" -> {
val key = rawArgs["key"] as String
val bundle: Bundle = rawArgs.__this__()
methodResult.success(bundle.getDouble(key))
}
"android.os.Bundle::getAll" -> {
val bundle: Bundle = rawArgs.__this__()
val result: MutableMap<String, Any?> = mutableMapOf()
for (item in bundle.keySet()) {
result[item] = bundle.get(item)
}
methodResult.success(result)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,21 @@
package me.yohom.foundation_fluttify.android.util
import android.util.Pair
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
fun PairHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.util.Pair::getFirst" -> {
val pair: Pair<*, *> = rawArgs.__this__()
methodResult.success(pair.first)
}
"android.util.Pair::getSecond" -> {
val pair: Pair<*, *> = rawArgs.__this__()
methodResult.success(pair.second)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,75 @@
package me.yohom.foundation_fluttify.android.view
import android.view.SurfaceHolder
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.get
fun SurfaceHolderHandler(
messenger: BinaryMessenger?,
method: String,
rawArgs: Any,
methodResult: MethodChannel.Result
) {
when (method) {
"android.view.SurfaceHolder::addCallback" -> {
val __this__ = rawArgs["__this__"] as SurfaceHolder
__this__.addCallback(object : SurfaceHolder.Callback {
private val channel =
MethodChannel(messenger!!, "android.view.SurfaceHolder::addCallback::Callback")
override fun surfaceCreated(p0: SurfaceHolder) {
print("kotlin: onSurfaceCreated")
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceCreated",
mapOf("var1" to p0)
)
}
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
print("kotlin: surfaceChanged")
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceChanged",
mapOf("var1" to p0, "var2" to p1, "var3" to p2, "var4" to p3)
)
}
override fun surfaceDestroyed(p0: SurfaceHolder) {
print("kotlin: surfaceDestroyed")
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceDestroyed",
mapOf("var1" to p0)
)
}
// override fun surfaceCreated(p0: SurfaceHolder) {
// print("kotlin: onSurfaceCreated")
// channel.invokeMethod(
// "Callback::android.view.SurfaceHolder.Callback::surfaceCreated",
// mapOf("var1" to p0)
// )
// }
//
// override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
// print("kotlin: surfaceChanged")
// channel.invokeMethod(
// "Callback::android.view.SurfaceHolder.Callback::surfaceChanged",
// mapOf("var1" to p0, "var2" to p1, "var3" to p2, "var4" to p3)
// )
// }
//
// override fun surfaceDestroyed(p0: SurfaceHolder) {
// print("kotlin: surfaceDestroyed")
// channel.invokeMethod(
// "Callback::android.view.SurfaceHolder.Callback::surfaceDestroyed",
// mapOf("var1" to p0)
// )
// }
})
methodResult.success("success")
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,25 @@
package me.yohom.foundation_fluttify.android.view
import android.view.SurfaceView
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.get
fun SurfaceViewHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.view.SurfaceView::getHolder" -> {
val __this__ = rawArgs["__this__"] as SurfaceView
methodResult.success(__this__.holder)
}
"android.view.SurfaceView::setZOrderOnTop" -> {
val __this__ = rawArgs["__this__"] as SurfaceView
__this__.setZOrderOnTop(rawArgs["onTop"] as Boolean)
methodResult.success("success")
}
"android.view.SurfaceView::setZOrderMediaOverlay" -> {
val __this__ = rawArgs["__this__"] as SurfaceView
__this__.setZOrderMediaOverlay(rawArgs["isMediaOverlay"] as Boolean)
methodResult.success("success")
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,28 @@
package me.yohom.foundation_fluttify.android.view
import android.view.View
import android.view.ViewGroup
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun ViewGroupHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"android.view.ViewGroup::addView" -> {
val viewGroup: ViewGroup = rawArgs.__this__()
val child: View = rawArgs["child"] as View
viewGroup.addView(child)
methodResult.success("success")
}
"android.view.ViewGroup::removeAllViews" -> {
val viewGroup: ViewGroup = rawArgs.__this__()
viewGroup.removeAllViews()
methodResult.success("success")
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,9 @@
package me.yohom.foundation_fluttify.android.view
import io.flutter.plugin.common.MethodChannel
fun ViewHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,32 @@
package me.yohom.foundation_fluttify.android.widget
import android.app.Activity
import android.graphics.Bitmap
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.__this__
import me.yohom.foundation_fluttify.core.get
fun ImageViewHandler(
method: String,
rawArgs: Any,
methodResult: MethodChannel.Result,
context: Activity?
) {
when (method) {
"android.widget.ImageView::createWithBitmap" -> {
if (context == null) {
methodResult.error("activity cannot be null", "activity cannot be null", "activity cannot be null")
} else {
val bitmap = rawArgs["bitmap"] as Bitmap
val imageView = ImageView(context)
imageView.setImageBitmap(bitmap)
methodResult.success(imageView)
}
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,11 @@
@file:Suppress("ObjectPropertyName", "FunctionName")
package me.yohom.foundation_fluttify.core
fun <T> Any.__this__(): T {
return (this as Map<String, Any>)["__this__"] as T
}
operator fun Any.get(key: String): Any? {
return (this as Map<String, Any>)[key]
}

View File

@ -0,0 +1,181 @@
@file:Suppress("LocalVariableName", "FunctionName")
package me.yohom.foundation_fluttify.core
import android.app.Activity
import android.content.Intent
import android.util.Log
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry
import me.yohom.foundation_fluttify.HEAP
import me.yohom.foundation_fluttify.STACK
import me.yohom.foundation_fluttify.enableLog
fun PlatformService(
method: String,
args: Map<String, Any>,
methodResult: MethodChannel.Result,
activityBinding: ActivityPluginBinding?,
pluginBinding: FlutterPlugin.FlutterPluginBinding?,
registrar: PluginRegistry.Registrar?
) {
when (method) {
"PlatformService::enableLog" -> {
enableLog = args["enable"] as Boolean
methodResult.success("success")
}
"PlatformService::release" -> {
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, 释放对象: ${args["__this__"]}")
HEAP.remove(args["__this__"])
methodResult.success("success")
// print current HEAP
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, HEAP: $HEAP")
}
"PlatformService::isNull" -> {
methodResult.success(args["__this__"] == null)
}
"PlatformService::release_batch" -> {
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, 批量释放对象: __this_batch__: ${args["__this_batch__"]}")
(args["__this_batch__"] as List<*>).forEach { HEAP.remove(it) }
methodResult.success("success")
// print current HEAP
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, HEAP: $HEAP")
}
"PlatformService::clearHeap" -> {
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, CLEAR HEAP")
HEAP.clear()
methodResult.success("success")
// print current HEAP
if (enableLog) Log.d("PlatformService", "size: ${HEAP.size}, HEAP: $HEAP")
}
"PlatformService::pushStack" -> {
val name = args["name"] as String
val __this__ = args["__this__"] as Any
if (enableLog) Log.d("PlatformService", "PUSH OBJECT: $__this__")
STACK[name] = __this__
methodResult.success("success")
// print current STACK
if (enableLog) Log.d("PlatformService", "size: ${STACK.size}, STACK: $STACK")
}
"PlatformService::pushStackJsonable" -> {
val name = args["name"] as String
val data = args["data"]
if (enableLog) Log.d("PlatformService", "压入jsonable: ${data?.javaClass}@${data}")
STACK[name] = data!!
methodResult.success("success")
// 打印当前STACK
if (enableLog) Log.d("PlatformService", "size: ${STACK.size}, STACK: $STACK")
}
"PlatformService::clearStack" -> {
STACK.clear()
methodResult.success("success")
// print current STACK
if (enableLog) Log.d("PlatformService", "size: ${STACK.size}, STACK: $STACK")
}
"PlatformService::startActivity" -> {
val activity = activityBinding?.activity
if (activity != null) {
val activityClass = args["activityClass"] as String
val extras = args["extras"] as Map<String, Any>
val intent = Intent(activity, Class.forName(activityClass))
extras.forEach {
when (it.value) {
is String -> intent.putExtra(it.key, it.value as String)
is Int -> intent.putExtra(it.key, it.value as Int)
is Long -> intent.putExtra(it.key, it.value as Long)
is Double -> intent.putExtra(it.key, it.value as Double)
}
}
activity.startActivity(intent)
methodResult.success("success")
} else {
methodResult.error("当前Activity为null", "当前Activity为null", "当前Activity为null")
}
}
"PlatformService::startActivityForResult" -> {
val activity = activityBinding?.activity
if (activity != null) {
val activityClass = args["activityClass"] as String
val requestCode = args["requestCode"] as Int
val extras = args["extras"] as Map<String, Any>
val intent = Intent(activity, Class.forName(activityClass))
extras.forEach {
when (it.value) {
is String -> intent.putExtra(it.key, it.value as String)
is Int -> intent.putExtra(it.key, it.value as Int)
is Long -> intent.putExtra(it.key, it.value as Long)
is Double -> intent.putExtra(it.key, it.value as Double)
}
}
activity.startActivityForResult(intent, requestCode)
activityBinding.addActivityResultListener { reqCode, resultCode, data ->
if (reqCode == requestCode) {
if (resultCode == Activity.RESULT_OK) {
methodResult.success(data)
} else {
methodResult.error("获取Activity结果失败", "获取Activity结果失败", "获取Activity结果失败")
}
} else {
methodResult.error("非当前请求的响应", "非当前请求的响应", "非当前请求的响应")
}
true
}
methodResult.success("success")
} else {
methodResult.error("当前Activity为null", "当前Activity为null", "当前Activity为null")
}
}
"PlatformService::getAssetPath" -> {
val activity = activityBinding?.activity
val flutterAssetPath = args["flutterAssetPath"] as String
if (activity != null) {
val path = registrar?.lookupKeyForAsset(flutterAssetPath)
?: pluginBinding?.flutterAssets?.getAssetFilePathByName(flutterAssetPath)
methodResult.success(path)
} else {
methodResult.error("非当前请求的响应", "非当前请求的响应", "非当前请求的响应")
}
}
"PlatformService::viewId2RefId" -> {
val viewId = args["viewId"] as String
if (HEAP.containsKey(viewId)) {
methodResult.success(System.identityHashCode(HEAP[viewId]).toString())
// 转换后删除viewId
HEAP.remove(viewId)
} else {
methodResult.error("viewId无对应对象", "viewId无对应对象", "viewId无对应对象")
}
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,17 @@
package me.yohom.foundation_fluttify.java.io
import io.flutter.plugin.common.MethodChannel
import me.yohom.foundation_fluttify.core.get
import java.io.File
fun FileHandler(method: String, rawArgs: Any, methodResult: MethodChannel.Result) {
when (method) {
"java.io.File::create" -> {
val path = rawArgs["path"] as String
val file = File(path)
methodResult.success(file)
}
else -> methodResult.notImplemented()
}
}

View File

@ -0,0 +1,27 @@
package me.yohom.foundation_fluttify.platform_view
import android.content.Context
import android.opengl.GLSurfaceView
import android.view.View
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import me.yohom.foundation_fluttify.HEAP
@Suppress("ClassName")
class android_opengl_GLSurfaceViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context?, id: Int, params: Any?): PlatformView {
val view = GLSurfaceView(context)
// 同时存放viewId和refId的对象, 供后续viewId转refId使用
HEAP[(Int.MAX_VALUE - id).toString()] = view
HEAP["android.opengl.GLSurfaceView:${System.identityHashCode(view)}"] = view
return object : PlatformView {
override fun getView(): View {
return view
}
override fun dispose() {}
}
}
}

View File

@ -0,0 +1,61 @@
package me.yohom.foundation_fluttify.platform_view
import android.content.Context
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import me.yohom.foundation_fluttify.HEAP
import me.yohom.foundation_fluttify.core.FluttifyMessageCodec
@Suppress("ClassName")
class android_view_SurfaceViewFactory(private val binaryMessenger: BinaryMessenger?)
: PlatformViewFactory(FluttifyMessageCodec()) {
override fun create(context: Context?, id: Int, params: Any?): PlatformView {
val view = SurfaceView(context)
view.holder.addCallback(object : SurfaceHolder.Callback {
private val channel = MethodChannel(
binaryMessenger!!,
"android.view.SurfaceHolder::addCallback::Callback",
StandardMethodCodec(FluttifyMessageCodec())
)
override fun surfaceCreated(holder: SurfaceHolder) {
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceCreated",
mapOf("holder" to holder)
)
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceChanged",
mapOf("holder" to holder, "format" to format, "width" to width, "height" to height)
)
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
channel.invokeMethod(
"Callback::android.view.SurfaceHolder.Callback::surfaceDestroyed",
mapOf("holder" to holder)
)
}
})
// 同时存放viewId和refId的对象, 供后续viewId转refId使用
HEAP[(Int.MAX_VALUE - id).toString()] = view
HEAP["android.view.SurfaceView:${System.identityHashCode(view)}"] = view
return object : PlatformView {
override fun getView(): View {
return view
}
override fun dispose() {}
}
}
}

View File

@ -0,0 +1,27 @@
package me.yohom.foundation_fluttify.platform_view
import android.content.Context
import android.view.View
import android.widget.FrameLayout
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import me.yohom.foundation_fluttify.HEAP
import me.yohom.foundation_fluttify.core.FluttifyMessageCodec
@Suppress("ClassName")
class android_widget_FrameLayoutFactory : PlatformViewFactory(FluttifyMessageCodec()) {
override fun create(context: Context?, id: Int, params: Any?): PlatformView {
val view = FrameLayout(context!!)
// 同时存放viewId和refId的对象, 供后续viewId转refId使用
HEAP[(Int.MAX_VALUE - id).toString()] = view
HEAP["android.widget.FrameLayout:${System.identityHashCode(view)}"] = view
return object : PlatformView {
override fun getView(): View {
return view
}
override fun dispose() {}
}
}
}