flutter与原生Android通信方式之MethodChannel

闲来无事,flutter好久没看了,上次折腾flutter与Android通信没折腾完,有些事情耽搁了,这次继续

演示效果:

flutter与Android原生通信

flutter端

复制代码
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class LikePages extends StatefulWidget {
  const LikePages({super.key});

  @override
  State<LikePages> createState() => _LikePagesState();
}

class _LikePagesState extends State<LikePages> {
  final MethodChannel _channel = MethodChannel('abc');
// Flutter 调用 Android 方法
  Future<void> callNativeMethod() async {
    try {
      final String result = await _channel.invokeMethod('getPlatformVersion');
      print('Result from Android: $result');
    } catch (e) {
      print('Error calling native method: $e');
    }
  }
  Future<void> callNativeOpenCameraMethod() async {
    try {
      final String result = await _channel.invokeMethod('openCamera');
      print('Result from Android: $result');
    } catch (e) {
      print('Error calling native method: $e');
    }
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('like'),
      ),
      body: Column(
        children: [
          Center(
            child: GestureDetector(child: Text('like'),onTap: (){
              // 调用 Flutter 调用 Android 方法
              callNativeMethod();
            },),
          ),
          Padding(
            padding: const EdgeInsets.all(80.0),
            child: Center(
              child: GestureDetector(child: Text('openCamare'),onTap: (){
                // 调用 Flutter 调用 Android 方法
                callNativeOpenCameraMethod();
              },),
            ),
          ),
        ],
      ),
    );
  }
}
Android端
复制代码
package com.example.f4

import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build.VERSION
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.widget.Toast
import androidx.annotation.NonNull
import androidx.annotation.Nullable
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.*


class MainActivity: FlutterActivity() {

    private val CHANNEL = "abc"
    private val REQUEST_IMAGE_CAPTURE = 1
    private val PERMISSION_REQUEST_CODE = 200
    var resultOut:MethodChannel.Result?=null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        XXPermissions.with(this) // 申请单个权限
            .permission(Permission.CAMERA) // 申请多个权限
            .permission(Permission.Group.CALENDAR) // 设置权限请求拦截器(局部设置)
            //.interceptor(new PermissionInterceptor())
            // 设置不触发错误检测机制(局部设置)
            //.unchecked()
            .request(object : OnPermissionCallback {
                override fun onGranted(permissions: List<String>, allGranted: Boolean) {
                    if (!allGranted) {
//                        Toast(this@MainActivity,"获取部分权限成功,但部分权限未正常授予",Toast.LENGTH_SHORT).show()
                        return
                    }
//                    toast("获取录音和日历权限成功")
                }

                override fun onDenied(permissions: List<String>, doNotAskAgain: Boolean) {
                    if (doNotAskAgain) {
//                        toast("被永久拒绝授权,请手动授予录音和日历权限")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(context, permissions)
                    } else {
//                        toast("获取录音和日历权限失败")
                    }
                }
            })
    }
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // 创建 MethodChannel
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            // 处理 Flutter 调用 Android 方法
            if (call.method == "getPlatformVersion") {
                result.success("Android ${VERSION.RELEASE}")
            }else if (call.method=="openCamera"){
                Log.e("TAG","call.method:="+call.method);
                resultOut = result
                dispatchTakePictureIntent()
            } else {
                result.notImplemented()
            }
        }
    }
    // 获取真实路径的函数
    private fun getRealPathFromUri(uri: Uri): String? {
        val projection = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = contentResolver.query(uri, projection, null, null, null)

        return cursor?.use {
            val columnIndex = it.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            it.moveToFirst()
            it.getString(columnIndex)
        }
    }
    fun saveBitmapToFile(context: Context, bitmap: Bitmap): String {
        val cw = ContextWrapper(context)
        val directory: File = cw.getDir("images", Context.MODE_PRIVATE)

        // 为文件生成唯一的名称
        val imageName = "img_${UUID.randomUUID()}.jpg"

        // 创建文件对象
        val file = File(directory, imageName)

        var fos: FileOutputStream? = null
        try {
            fos = FileOutputStream(file)
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos) // 将 Bitmap 压缩为 JPEG 格式
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                fos?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }

        // 返回文件的路径
        return file.absolutePath
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int,data: Intent) {
        super.onActivityResult(requestCode, resultCode, data)
        Log.e("TAG","==-->${data.extras}"+"  resultCode:=$resultCode "+" requestCode:$requestCode ")
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            // 图片从相机返回
            val extras = data.extras
            if (extras != null) {
                // 获取拍摄的照片
                val imageBitmap = extras.get("data") as Bitmap?

                // 保存 Bitmap 到文件并获取文件路径
                val imagePath = imageBitmap?.let { saveBitmapToFile(applicationContext, it) }

                // 在这里使用文件路径
                resultOut?.success(imagePath)
            }
        } else {
            Toast.makeText(this, "Failed to capture image", Toast.LENGTH_SHORT).show()
        }
    }
    private fun dispatchTakePictureIntent() {
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        if (takePictureIntent.resolveActivity(packageManager) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
        }
    }
}

上述代码演示了直接获取Android版本号,以及调用Android原生拍照并发挥图片路径到Flutter的方式,至于为什么会想要搞搞这个,原因还是在与Flutter插件的稳定性问题,假如要实现一个功能,但是受限于Flutter插件自身的问题,就只能自己来实现了,这时候通过原生代码返回需要的数据就不失为一种解决方案,

相关推荐
ForteScarlet1 小时前
从 Kotlin 编译器 API 的变化开始: 2.3.20
android·开发语言·后端·ios·开源·kotlin
私人珍藏库2 小时前
[Android] 假装来电 v1.1.0
android·app·工具·软件·多功能
spencer_tseng3 小时前
Android Studio [Gradle JDK]
android·ide·android studio
sun0077003 小时前
wifi热点的防火墙
android
Code-Porter3 小时前
记录关于Flutter ObjectBox数据库使用ObjectBoxBrowser插件,在同一个局域网内电脑无法访问查看数据问题
android·数据库·flutter·dart
钛态4 小时前
Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 深度对接企业级 Exchange 服务、实现鸿蒙端邮件与日程的高效分发及 SOAP 协议连接方案
flutter·harmonyos·鸿蒙·openharmony
亚历克斯神4 小时前
Flutter 三方库 jwt_io 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、严谨、全能的 JSON Web Token (JWT) 加解密与身份安全验证引擎
flutter·json·harmonyos
KongHen024 小时前
Android Studio最新版汉化教程(2025年10月17日)
android·ide·android studio
键盘鼓手苏苏4 小时前
Flutter for OpenHarmony:使用 typed_data 直击高性能底层数据操作核心
android·flutter·华为·自动化·harmonyos
加农炮手Jinx4 小时前
Flutter 组件 sse_stream 的适配 鸿蒙Harmony 深度进阶 - 驾驭高并发 Server-Sent Events 背压处理、实现鸿蒙端工业级 AI 响应流与长效链路治理方案
flutter·harmonyos·鸿蒙·openharmony·sse_stream