开发流程:
1、使用object-c和java语言模板创建插件项目,command line : flutter create --template=plugin -i objc -a java mobile_state
关键文件:
//这里是你的插件在dart 中引用的类文件,也就是衔接native的dart插件类
lib/mobile_state.dart
//这里是你的插件对应的原生android文件
android/src/main/java/com/example/mobile_state/MobileStatePlugin.java
2、修改 lib/mobile_state.dart 下对应的 MethodChannel 与 invokeMethod() 方法中的参数
3、 通过invokeMethod() 方法发送的消息,在 java类文件中的 onMethodCall 方法中进行统一入口判断与实现
4、通过result类返回信息传递给dart
5、本地引用插件
在项目的 pubspec.yml 文件的依赖部分声明插件名称,这里的名称必须和你插件项目中的 pubspec.yml 文件的 name 一致。
格式:
dependencies:
flutter:
sdk: flutter
[插件name]:
path: [插件的项目路径,可用绝对或相对路径]
参考:
dependencies:
flutter:
sdk: flutter
mobile_state:
path: /opt/coding/flutter/plugins/test/flutter_plugin_test/
注意事项:
1、因为dart 语言和flutter 快速发展,在插件的java文件中,会有 onAttachedToEngine 和 registerWith 两个方法,目的是将类注册到dart对应的MethodChannel 中,
这两个方法功能一致,在一个项目中,只会触发其中一个方法,如果你使用的是 flutter >= 1.12.x ,则只会触发 onAttachedToEngine方法,如果是 flutter <= 1.12.x 版本则会触发 registerWith .
所以,当你在不同的版本中需要调用原生的交互时,特别要注意应该使用哪个方法进行原生调用。
2、关于 插件中引用 activity 的方式.
在 registerWith 方法中,通过方法参数中的 Registrar registrar 参数,进行获取.
registrar.activity()
如果你是 1.12.x 版本,那么在插件类中实现 ActivityAware 接口。
参考代码:
public class MyPlugin implements FlutterPlugin, ActivityAware {
//...normal plugin behavior is hidden...
@Override
public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
// TODO: your plugin is now attached to an Activity
}
@Override
public void onDetachedFromActivityForConfigChanges() {
// TODO: the Activity your plugin was attached to was destroyed to change configuration.
// This call will be followed by onReattachedToActivityForConfigChanges().
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
// TODO: your plugin is now attached to a new Activity after a configuration change.
}
@Override
public void onDetachedFromActivity() {
// TODO: your plugin is no longer associated with an Activity. Clean up references.
}
}
参考链接: https://github.com/flutter/flutter/wiki/Experimental:-Create-Flutter-Plugin
3、关于插件中可能遇到的权限申请和检查,则在拿到activity后按android 开发方式进行开发即可。
步骤:
1、首先需要向 AndroidMainfest.xml中添加权限
2、在申请权限的插件类中实现权限回调方法 onRequestPermissionsResult
3、然后再使用 ActivityCompat.requestPermissions 方法动态申请权限。
这里注意一下权限申请方法参数的意义,对于一个新手,网上很多资料都没有说明清楚。
权限申请方法: ActivityCompat.requestPermissions
参数列表:
参数 | 说明 |
Activity activity | 当前申请权限的 activity,在插件类中通过实现ActivityAware 接口获取 |
String[] permissions | 申请权限数组,这个可以再网上找到android权限列表 |
int requestCode | 这个参数用于标识,哪个方法申请的权限,因为权限处理均在一个方法中,可能很多处代码均申请了权限,所以在处理时需要根据标识进行对应的返回结果处理。这个 requestCode 也会在 权限回调方法 onRequestPermissionsResult 中用上。 |
在插件中获取手机号码\IMEI等信息的完整参考代码:
package com.example.mobile_state;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import androidx.annotation.NonNull;
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.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;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import android.Manifest;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
/** MobileStatePlugin */
public class MobileStatePlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
private static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 0;
private static PluginRegistry.Registrar registrar;
private TelephonyManager telephonyManager;
static final String CHANNEL = "plugins.zcaij.com/mobile_state";
static Activity activity;
///activity 生命周期
@Override
public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
Log.e("onAttachedToActivity", "onAttachedToActivity");
activity = activityPluginBinding.getActivity();
}
@Override
public void onDetachedFromActivityForConfigChanges() {
Log.e("onDetachedFromActivityForConfigChanges", "onDetachedFromActivityForConfigChanges");
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
Log.e("onReattachedToActivityForConfigChanges", "onReattachedToActivityForConfigChanges");
}
@Override
public void onDetachedFromActivity() {
Log.e("onDetachedFromActivity", "onDetachedFromActivity");
}
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), CHANNEL);
channel.setMethodCallHandler(new MobileStatePlugin());
}
// This static function is optional and equivalent to onAttachedToEngine. It supports the old
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL);
channel.setMethodCallHandler(new MobileStatePlugin());
activity = registrar.activity();
}
void getNumber(){
String num = telephonyManager.getLine1Number();
Log.d("xxxxx",num);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
telephonyManager = (TelephonyManager)activity.getSystemService(Context.TELEPHONY_SERVICE);
if (call.method.equals("getPhoneNumber")) {
int x = activity.checkSelfPermission(Manifest.permission.READ_PHONE_STATE);
if(x != 0)
{
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_PHONE_STATE},
MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
}else{
getNumber();
}
result.success("xxxxx");
} else {
result.notImplemented();
}
}
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_PHONE_STATE: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
getNumber();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
}
}