flutter 1.12 版本插件開發與獲取權限總結

開發流程:

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) {
  }


}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章