• 赚钱入口【需求资源】限时招募流量主、渠道主,站长合作;【合作模式】CPS长期分成,一次推广永久有收益。主动打款,不扣量;

为Android和iOS创建 Flutter插件| ImageGallery

Flutter cps12345 1年前 (2020-06-25) 445次浏览 0个评论

什么是Flutter插件?

Flutter 插件是通过 Dart 语言对 Android(Kotlin或java)和iOS(swift或Objective c)代码进行一层封装的库。

MethodChannel用于将Android和iOS的本机代码传递给Flutter(Dart Code)。

这是对flutter插件的基本了解,现在让我们看看为什么需要插件。

为什么需要插件?

Flutter不支持地理位置,支付SDK,视频通话SDK等许多功能,如果我们想在 Flutter 项目中实现这些功能,则可以在Android和iOS本机代码中编写并实现这些自定义功能。

如何创建插件:

这些是创建插件的步骤:

打开Android Studio进入File >> New >> New flutter Project

 

单击 New Flutter Project>>Flutter Plugin。

 

设置插件名称:

 

现在,如果您在project_name-> lib下看到该文件,则将找到默认代码为

import 'dart:async';

import 'package:flutter/services.dart';

class FlutterGalleryPlugin {
  static const MethodChannel _channel =
      const MethodChannel('flutter_gallery_plugin');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

上面的代码将与您将在Android和iOS文件中编写的本机代码进行通信。

Android原生代码(java代码):

您将在Android部分中找到此代码(project_name-> android)

package com.example.fluttergalleryplugin;

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;

/** FlutterGalleryPlugin */
public class FlutterGalleryPlugin implements MethodCallHandler {
  /** Plugin registration. */
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_gallery_plugin");
    channel.setMethodCallHandler(new FlutterGalleryPlugin());
  }

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }
}

同样适用于iOS,您会在中找到初始的默认代码

project_name-> ios

iOS原生代码:

import Flutter

import UIKit

public class SwiftFlutterGallaryPlugin: NSObject, FlutterPlugin {

public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "dialog_box_plugin", binaryMessenger: registrar.messenger())

let instance = SwiftFlutterGallaryPlugin()

registrar.addMethodCallDelegate(instance, channel: channel)

}

public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {

result("iOS " + UIDevice.current.systemVersion)

}

}

由于我们想调用返回输出的方法(在本例中,我们将接收所有图像),invoke方法将用Dart编写

Dart文件(project_name-> lib):

import 'dart:async';

import 'package:flutter/services.dart';

class FlutterGalleryPlugin {
  static const MethodChannel _channel =
      const MethodChannel('flutter_gallery_plugin');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

Android 原生代码(project_name-> android-> src):

package adhoc.successive.com.fluttergallaryplugin;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Application;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionDeniedResponse;
import com.karumi.dexter.listener.PermissionGrantedResponse;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.single.PermissionListener;

import java.util.ArrayList;

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;
/**
 * FlutterGallaryPlugin
 */

/**
 * FlutterGallaryPlugin
 */
public class FlutterGallaryPlugin implements MethodCallHandler {
    Activity activity;
    MethodChannel methodChannel;
    private Application.ActivityLifecycleCallbacks activityLifecycleCallbacks;
    Result result;

    public static void registerWith(Registrar registrar) {
        final MethodChannel channel = new MethodChannel(registrar.messenger(), "image_gallery");
        channel.setMethodCallHandler(new FlutterGallaryPlugin(registrar.activity(), channel, registrar));
    }

    public FlutterGallaryPlugin(Activity activity, MethodChannel methodChannel, Registrar registrar) {
        this.activity = activity;
        this.methodChannel = methodChannel;
        this.methodChannel.setMethodCallHandler(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            this.activityLifecycleCallbacks =
                    new Application.ActivityLifecycleCallbacks() {
                        @Override
                        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                        }

                        @Override
                        public void onActivityStarted(Activity activity) {
                        }

                        @Override
                        public void onActivityResumed(Activity activity) {
                            getPermissionResult(result, activity);
                        }

                        @Override
                        public void onActivityPaused(Activity activity) {
                        }

                        @Override
                        public void onActivityStopped(Activity activity) {
                        }

                        @Override
                        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
                        }

                        @Override
                        public void onActivityDestroyed(Activity activity) {
                        }
                    };
        }
    }

    @Override
    public void onMethodCall(MethodCall call, Result result) {
        this.result = result;
        if (call.method.equals("getAllImages")) {
            getPermissionResult(result, activity);
        } else {
            result.notImplemented();
        }
    }


    public void getPermissionResult(final Result result, final Activity activity) {
        Dexter.withActivity(activity)
                .withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .withListener(new PermissionListener() {
                    @Override
                    public void onPermissionGranted(PermissionGrantedResponse response) {
                        result.success(getAllImageList(activity));
                    }

                    @Override
                    public void onPermissionDenied(PermissionDeniedResponse response) {
                        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                        builder.setMessage("This permission is needed for use this features of the app so please, allow it!");
                        builder.setTitle("We need this permission");
                        builder.setCancelable(false);
                        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                                Intent intent = new Intent();
                                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                                Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
                                intent.setData(uri);
                                activity.startActivity(intent);
                            }
                        });
                        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                            }
                        });
                        AlertDialog alert = builder.create();
                        alert.show();


                    }

                    @Override
                    public void onPermissionRationaleShouldBeShown(PermissionRequest permission, final PermissionToken token) {
                        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
                        builder.setMessage("This permission is needed for use this features of the app so please, allow it!");
                        builder.setTitle("We need this permission");
                        builder.setCancelable(false);
                        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                                token.continuePermissionRequest();
                            }
                        });
                        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                dialog.cancel();
                                token.cancelPermissionRequest();
                            }
                        });
                        AlertDialog alert = builder.create();
                        alert.show();
                    }
                }).check();
    }

    public ArrayList<String> getAllImageList(Activity activity) {
        ArrayList<String> allImageList = new ArrayList<>();
        Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        String[] projection = {MediaStore.Images.ImageColumns.DATA,
                MediaStore.Images.ImageColumns.DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATE_ADDED,
                MediaStore.Images.ImageColumns.TITLE};
        Cursor c = activity.getContentResolver().query(uri, projection, null, null, null);
        if (c != null) {
            while (c.moveToNext()) {
                //  ImageModel imageModel = new ImageModel();
                Log.e("", "getAllImageList: " + c.getString(0));
                Log.e("", "getAllImageList: " + c.getString(1));
                Log.e("", "getAllImageList: " + c.getString(2));
                allImageList.add(c.getString(0));
            }
            c.close();
        }
        return allImageList;
    }
}

iOS 原生代码(project_name -> iOS -> Classes)

import Flutter
import UIKit
import Photos

public class SwiftFlutterGallaryPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "image_gallery", binaryMessenger: registrar.messenger())
        let instance = SwiftFlutterGallaryPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        if (call.method == "getPlatformVersion") {
            result("iOS " + UIDevice.current.systemVersion)
        }
        else if (call.method == "getAllImages") {
            
            DispatchQueue.main.async {
                
                let imgManager = PHImageManager.default()
                let requestOptions = PHImageRequestOptions()
                requestOptions.isSynchronous = true
                let fetchOptions = PHFetchOptions()
                fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]
                
                let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
                var allImages = [String]()
                
                var totalItration = 0
                print("fetchResult.count : \(fetchResult.count)")
                
                var savedLocalIdentifiers = [String]()
                
                for index in 0..<fetchResult.count
                {
                    let asset = fetchResult.object(at: index) as PHAsset
                    let localIdentifier = asset.localIdentifier
                    savedLocalIdentifiers.append(localIdentifier)
                    
                    imgManager.requestImage(for: asset, targetSize: CGSize(width: 512.0, height: 512.0), contentMode: PHImageContentMode.aspectFit, options: PHImageRequestOptions(), resultHandler:{(image, info) in
                        
                        if image != nil {
                            var imageData: Data?
                            if let cgImage = image!.cgImage, cgImage.renderingIntent == .defaultIntent {
                                imageData = UIImageJPEGRepresentation(image!, 0.8)
                            }
                            else {
                                imageData = UIImagePNGRepresentation(image!)
                            }
                            let guid = ProcessInfo.processInfo.globallyUniqueString;
                            let tmpFile = String(format: "image_picker_%@.jpg", guid);
                            let tmpDirectory = NSTemporaryDirectory();
                            let tmpPath = (tmpDirectory as NSString).appendingPathComponent(tmpFile);
                            if(FileManager.default.createFile(atPath: tmpPath, contents: imageData, attributes: [:])) {
                                allImages.append(tmpPath)
                            }
                        }
                        totalItration += 1
                        if totalItration == (fetchResult.count) {
                            result(allImages)
                        }
                    })
                }
            }
        }
    }
}

现在插件就可以使用了

前往 example/lib 然后替换为下面的代码:

import Flutter
import UIKit
import Photos

public class SwiftFlutterGallaryPlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "image_gallery", binaryMessenger: registrar.messenger())
        let instance = SwiftFlutterGallaryPlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        if (call.method == "getPlatformVersion") {
            result("iOS " + UIDevice.current.systemVersion)
        }
        else if (call.method == "getAllImages") {
            
            DispatchQueue.main.async {
                
                let imgManager = PHImageManager.default()
                let requestOptions = PHImageRequestOptions()
                requestOptions.isSynchronous = true
                let fetchOptions = PHFetchOptions()
                fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]
                
                let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
                var allImages = [String]()
                
                var totalItration = 0
                print("fetchResult.count : \(fetchResult.count)")
                
                var savedLocalIdentifiers = [String]()
                
                for index in 0..<fetchResult.count
                {
                    let asset = fetchResult.object(at: index) as PHAsset
                    let localIdentifier = asset.localIdentifier
                    savedLocalIdentifiers.append(localIdentifier)
                    
                    imgManager.requestImage(for: asset, targetSize: CGSize(width: 512.0, height: 512.0), contentMode: PHImageContentMode.aspectFit, options: PHImageRequestOptions(), resultHandler:{(image, info) in
                        
                        if image != nil {
                            var imageData: Data?
                            if let cgImage = image!.cgImage, cgImage.renderingIntent == .defaultIntent {
                                imageData = UIImageJPEGRepresentation(image!, 0.8)
                            }
                            else {
                                imageData = UIImagePNGRepresentation(image!)
                            }
                            let guid = ProcessInfo.processInfo.globallyUniqueString;
                            let tmpFile = String(format: "image_picker_%@.jpg", guid);
                            let tmpDirectory = NSTemporaryDirectory();
                            let tmpPath = (tmpDirectory as NSString).appendingPathComponent(tmpFile);
                            if(FileManager.default.createFile(atPath: tmpPath, contents: imageData, attributes: [:])) {
                                allImages.append(tmpPath)
                            }
                        }
                        totalItration += 1
                        if totalItration == (fetchResult.count) {
                            result(allImages)
                        }
                    })
                }
            }
        }
    }
}

 

运行结果屏幕截图:

为Android和iOS创建 Flutter插件| ImageGallery

如何发布插件:

以下是将插件发布到https://pub.dartlang.org/的以下命令

flutter packages pub publish--dry-run
flutter packages pub publish

您可以从此Github存储库中获得该演示的完整源代码。

https://github.com/flutter-devs/image_gallery

喜欢 (0)

您必须 登录 才能发表评论!