2026-05-15 21:20:29 +08:00

259 lines
9.1 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// FlutterPagPlugin.m
// FlutterPagPlugin
//
// Created by 黎敬茂 on 2022/3/14.
// Copyright © 2022 Tencent. All rights reserved.
//
#import "FlutterPagPlugin.h"
#import "TGFlutterPagRender.h"
#import "TGFlutterPagDownloadManager.h"
/**
FlutterPagPlugin处理flutter MethodChannel约定的方法
*/
#define PlayCallback @"PAGCallback"
#define ArgumentEvent @"PAGEvent"
#define ArgumentTextureId @"textureId"
@interface FlutterPagPlugin()
/// flutter引擎注册的textures对象
@property(nonatomic, weak) NSObject<FlutterTextureRegistry>* textures;
/// flutter引擎注册的registrar对象
@property(nonatomic, weak) NSObject<FlutterPluginRegistrar>* registrar;
/// 保存textureId跟render对象的对应关系
@property (nonatomic, strong) NSMutableDictionary *renderMap;
/// pag对象的缓存
@property (nonatomic, strong)NSCache<NSString*, NSData *> *cache;
/// 用于通信的channel
@property (nonatomic, strong)FlutterMethodChannel* channel;
@end
@implementation FlutterPagPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_pag_plugin"
binaryMessenger:[registrar messenger]];
FlutterPagPlugin* instance = [[FlutterPagPlugin alloc] init];
instance.textures = registrar.textures;
instance.registrar = registrar;
instance.channel = channel;
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)getLayersUnderPoint:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
NSNumber* x = arguments[@"x"];
NSNumber* y = arguments[@"y"];
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
NSArray<NSString *> *names = [render getLayersUnderPoint:CGPointMake(x.doubleValue, y.doubleValue)];
result(names);
}
- (void)release:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
if(textureId == nil){
result(@"");
return;
}
[self.textures unregisterTexture:textureId.intValue];
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
[render releaseRender];
[_renderMap removeObjectForKey:textureId];
result(@"");
}
- (void)setProgress:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
if(textureId == nil){
result(@"");
return;
}
double progress = 0.0;
if (arguments[@"progress"]) {
progress = [arguments[@"progress"] doubleValue];
}
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
[render setProgress:progress];
result(@"");
}
- (void)pause:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
if(textureId == nil){
result(@"");
return;
}
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
[render pauseRender];
result(@"");
}
- (void)stop:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
if(textureId == nil){
result(@"");
return;
}
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
[render stopRender];
result(@"");
}
- (void)start:(id)arguments result:(FlutterResult _Nonnull)result {
NSNumber* textureId = arguments[@"textureId"];
if(textureId == nil){
result(@"");
return;
}
TGFlutterPagRender *render = [_renderMap objectForKey:textureId];
[render startRender];
result(@"");
}
- (void)initPag:(id)arguments result:(FlutterResult _Nonnull)result {
if (arguments == nil || (arguments[@"assetName"] == NSNull.null && arguments[@"url"] == NSNull.null && arguments[@"bytesData"] == NSNull.null)) {
result(@-1);
NSLog(@"showPag arguments is nil");
return;
}
double initProgress = 0.0;
if (arguments[@"initProgress"]) {
initProgress = [arguments[@"initProgress"] doubleValue];
}
int repeatCount = -1;
if(arguments[@"repeatCount"]){
repeatCount = [[arguments objectForKey:@"repeatCount"] intValue];
}
BOOL autoPlay = NO;
if(arguments[@"autoPlay"]){
autoPlay = [[arguments objectForKey:@"autoPlay"] boolValue];
}
NSString* assetName = arguments[@"assetName"];
NSData *pagData = nil;
if ([assetName isKindOfClass:NSString.class] && assetName.length > 0) {
NSString *key = assetName;
pagData = [self getCacheData:key];
if (!pagData) {
NSString* package = arguments[@"package"];
NSString* resourcePath;
if(package && [package isKindOfClass:NSString.class] && package.length > 0){
resourcePath = [self.registrar lookupKeyForAsset:assetName fromPackage:package];
}else{
resourcePath = [self.registrar lookupKeyForAsset:assetName];
}
resourcePath = [[NSBundle mainBundle] pathForResource:resourcePath ofType:nil];
pagData = [NSData dataWithContentsOfFile:resourcePath];
[self setCacheData:key data:pagData];
}
[self pagRenderWithPagData:pagData progress:initProgress repeatCount:repeatCount autoPlay:autoPlay result:result];
}
NSString* url = arguments[@"url"];
if ([url isKindOfClass:NSString.class] && url.length > 0) {
NSURLSessionDownloadTask *task;
[task resume];
NSString *key = url;
pagData = [self getCacheData:key];
if (!pagData) {
__weak typeof(self) weak_self = self;
[TGFlutterPagDownloadManager download:url completionHandler:^(NSData * _Nonnull data, NSError * _Nonnull error) {
if (data) {
[weak_self setCacheData:key data:pagData];
[weak_self pagRenderWithPagData:data progress:initProgress repeatCount:repeatCount autoPlay:autoPlay result:result];
}else{
result(@-1);
}
}];
}else{
[self pagRenderWithPagData:pagData progress:initProgress repeatCount:repeatCount autoPlay:autoPlay result:result];
}
}
id bytesData = arguments[@"bytesData"];
if(bytesData != nil && [bytesData isKindOfClass:FlutterStandardTypedData.class]){
FlutterStandardTypedData *typedData = bytesData;
if(typedData.type == FlutterStandardDataTypeUInt8 && typedData.data != nil){
[self pagRenderWithPagData:typedData.data progress:initProgress repeatCount:repeatCount autoPlay:autoPlay result:result];
}else{
result(@-1);
}
}
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
id arguments = call.arguments;
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else if([@"initPag" isEqualToString:call.method]){
[self initPag:arguments result:result];
} else if([@"start" isEqualToString:call.method]){
[self start:arguments result:result];
} else if([@"stop" isEqualToString:call.method]){
[self stop:arguments result:result];
} else if([@"pause" isEqualToString:call.method]){
[self pause:arguments result:result];
} else if([@"setProgress" isEqual:call.method]){
[self setProgress:arguments result:result];
} else if([@"release" isEqualToString:call.method]){
[self release:arguments result:result];
} else if([@"getLayersUnderPoint" isEqualToString:call.method]){
[self getLayersUnderPoint:arguments result:result];
} else {
result(FlutterMethodNotImplemented);
}
}
-(void)pagRenderWithPagData:(NSData *)pagData progress:(double)progress repeatCount:(int)repeatCount autoPlay:(BOOL)autoPlay result:(FlutterResult)result{
__block int64_t textureId = -1;
__weak typeof(self) weakSelf = self;
TGFlutterPagRender *render = [[TGFlutterPagRender alloc] initWithPagData:pagData progress:progress frameUpdateCallback:^{
[weakSelf.textures textureFrameAvailable:textureId];
} eventCallback:^(NSString * event) {
[weakSelf.channel invokeMethod:PlayCallback arguments:@{ArgumentTextureId:@(textureId), ArgumentEvent:event}];
}];
[render setRepeatCount:repeatCount];
textureId = [self.textures registerTexture:render];
if(_renderMap == nil){
_renderMap = [[NSMutableDictionary alloc] init];
}
[_renderMap setObject:render forKey:@(textureId)];
result(@{@"textureId":@(textureId), @"width":@([render size].width), @"height":@([render size].height)});
if(autoPlay){
[render startRender];
}
}
-(NSData *)getCacheData:(NSString *)key{
return [self.cache objectForKey:key];
}
-(void)setCacheData:(NSString *)key data:(NSData *)data{
if (data == nil || key == nil) {
return;
}
[self.cache setObject:data forKey:key cost:data.length];
}
-(NSCache *)cache{
if (!_cache) {
_cache = [[NSCache alloc] init];
///缓存64m
_cache.totalCostLimit = 64*1024*1024;
_cache.countLimit = 32;
}
return _cache;
}
@end