某些场景下或者现有pub插件无法满足我们的需求的时候需要自己写一个插件

现在有这样一个场景,需要给定一个图片的url,然后下载图片到指定目录中(/storage/emulated/0/Android/data/com.zx.plugintest/files/Caches)。现在有一个插件,image_gallery_saver ,但它将网络文件保存在了我们的相册目录中。

 

1、在flutter根目录下新建一个flutter 插件

打开androidstudio terminal 

flutter create --template=plugin  --org com.zx --platforms=android,ios -a java -i swift save_img_plugin

其中 com.zx 是插件包名的一部分,save_img_plugin 是插件的名称。插件的完整包名为 com.zx.save_img_plugin

为什么没有使用IDE 的选项创建呢,我创建出来没有android 和 ios的原生工程目录 

参考 https://blog.csdn.net/zytry/article/details/108997168

2、pubspec.yaml 添加插件

save_img_plugin:  path: save_img_plugin

pub get 一下

3、在插件的lib\save_pic_plugin.dart添加如下代码

static Future saveImage(Uint8List imageBytes,      {int quality = 80, String name}) async {    assert(imageBytes != null);    final result =    await _channel.invokeMethod('saveImageToLocal', {      'imageBytes': imageBytes,      'quality': quality,      'name': name,    });    return result;  }

这里的代码是给其他flutter调用者 提供的外部接口。

4、实现native调用方法

package com.zx.save_img_plugin;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import androidx.annotation.NonNull;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import io.flutter.Log;import io.flutter.embedding.engine.plugins.FlutterPlugin;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;/** SaveImgPlugin */public class SaveImgPlugin implements FlutterPlugin, MethodCallHandler {  private static final String TAG = "SaveImgPlugin";  private MethodChannel channel;  private Context mContext;  @Override  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {    channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "save_img_plugin");    channel.setMethodCallHandler(this);    mContext = flutterPluginBinding.getApplicationContext();  }  @Override  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {    Log.d(TAG,"---onMethodCall---");    if (call.method.equals("saveImageToLocal")) {      byte[] image = null;      int quality = 100;      String name = "splash.jpg";      if (null != call.argument("imageBytes")) {        image = call.argument("imageBytes");      } else {        result.error("the argument imageBytes is null","","");      }      if (null != call.argument("name")) {        name = call.argument("name");      }      if (null != call.argument("quality")) {        quality = call.argument("quality");        if(quality <= 0 || quality>100) {          result.error("the quality is in range(0,100]","","");        }      }      result.success(saveImageToLocal(BitmapFactory.decodeByteArray(image,0,image.length), quality, name));    }  }  private boolean saveImageToLocal(Bitmap bmp, int quality, String name) {    Log.d(TAG,"---saveImageToLocal---");    Context context = mContext.getApplicationContext();    String cacheDir = context.getExternalFilesDir("Caches").getPath();    Log.d(TAG,"---cacheDir---" + cacheDir);    File file = new File(cacheDir + File.separator + name);  //将图片保存到刚创建好的目录下    try {      FileOutputStream out = new FileOutputStream(file);      if (bmp != null) {        bmp.compress(Bitmap.CompressFormat.JPEG, quality, out);      }      out.close();      return true;    } catch (IOException e) {      e.printStackTrace();    }    return false;  }  @Override  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {    channel.setMethodCallHandler(null);  }}

注意 :

1、flutter (save_pic_plugin.dart)传递的参数 saveImageToLocal 必须和 原生 if (call.method.equals("saveImageToLocal"))  中判断的名称相同才能进入对应逻辑。

2、平台通道数据类型支持

平台通道使用标准消息编/解码器对消息进行编解码,它可以高效的对消息进行二进制序列化与反序列化。由于Dart与原生平台之间数据类型有所差异,下面我们列出数据类型之间的映射关系。

Dart Android iOS
null null nil (NSNull when nested)
bool java.lang.Boolean NSNumber numberWithBool:
int java.lang.Integer NSNumber numberWithInt:
int, 如果不足32位 java.lang.Long NSNumber numberWithLong:
int, 如果不足64位 java.math.BigInteger FlutterStandardBigInteger
double java.lang.Double NSNumber numberWithDouble:
String java.lang.String NSString
Uint8List byte[] FlutterStandardTypedData typedDataWithBytes:
Int32List int[] FlutterStandardTypedData typedDataWithInt32:
Int64List long[] FlutterStandardTypedData typedDataWithInt64:
Float64List double[] FlutterStandardTypedData typedDataWithFloat64:
List java.util.ArrayList NSArray
Map java.util.HashMap NSDictionary

当在发送和接收值时,这些值在消息中的序列化和反序列化会自动进行。

在android 清单文件中添加两个权限

至于权限怎么添加和使用,方式如下:

5、新建一个permission.dart

import 'package:permission_handler/permission_handler.dart';Future requestStoragePermission() async {  final storageStatus = await PermissionHandler().requestPermissions([PermissionGroup.storage]);  if (storageStatus[PermissionGroup.storage] == PermissionStatus.granted) {    return true;  } else {    return false;  }}

6、使用

import 'Permission.dart' as Permission;void savePic() async {    Permission.requestStoragePermission().then((value)  async {      if(value) {        var response = await Dio().get(            "https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a62e824376d98d1069d40a31113eb807/838ba61ea8d3fd1fc9c7b6853a4e251f94ca5f46.jpg",            options: Options(responseType: ResponseType.bytes));        SaveImgPlugin.saveImage(Uint8List.fromList(response.data),quality:100,name:'mypic1.png').then((value) {          setState(() {            tip = 'down load over';          });        });      }    });  }

完后在日志中找到 ---cacheDir---/storage/emulated/0/Android/data/com.zx.plugintestapp/files/Caches  ,这个里面就有我们下载好的图片文件。

ok,整个插件的基础开发就是这些了。

 

 

 

 

 

 

更多相关文章

  1. Android(安卓)Looper和Handler分析
  2. Android(安卓)wifi-framework WifiMonitor和WifiNative学习
  3. android消息机制(handler运行机制)解析
  4. android Handler,Looper,Message三者关系
  5. Android开发: 线程间消息通信 Looper 和Handler
  6. Android(安卓)开发中Parcel存储类型和数据容器
  7. Android动态换肤(二、apk免安装插件方式)
  8. Android(安卓)Studio学习之安装插件
  9. 即将到来的Android(安卓)N,将具备这些新特性

随机推荐

  1. Android中Intent传值
  2. Android(安卓)加载大图片是出现的 OutOfM
  3. android中使用SQLite进行CRUD操作的实例
  4. Android的pagerAdapter源码,在线查看网址
  5. android 图片的浏览、缩放、拖动和自动居
  6. 设置 Toolbar(ActionBar) 上的按钮颜色
  7. android 安装软件
  8. Android(安卓)如何实现屏幕转换方向
  9. Android布局管理器
  10. Android(安卓)System Server