閑來無事,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});@overrideState<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');}}@overrideWidget 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.f4import 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 = 1private val PERMISSION_REQUEST_CODE = 200var resultOut:MethodChannel.Result?=nulloverride 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)// 創建 MethodChannelMethodChannel(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 = resultdispatchTakePictureIntent()} 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? = nulltry {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.extrasif (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插件自身的問題,就只能自己來實現了,這時候通過原生代碼返回需要的數據就不失為一種解決方案,