add 扫码打开小程序的功能
parent
360e9adfb2
commit
33f965c995
5
Podfile
5
Podfile
|
@ -1,11 +1,16 @@
|
|||
platform :ios, "9.0"
|
||||
|
||||
source 'https://cdn.cocoapods.org/'
|
||||
|
||||
|
||||
inhibit_all_warnings!
|
||||
|
||||
target "demo" do
|
||||
pod 'FinApplet'
|
||||
pod 'FinAppletExt'
|
||||
pod 'FinAppletWebRTC'
|
||||
pod 'FinAppletBDMap'
|
||||
pod 'FinAppletGDMap'
|
||||
pod 'WechatOpenSDK'
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
9DD565BE23EC45080011FC4A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD565BD23EC45080011FC4A /* AppDelegate.m */; };
|
||||
9DD565C423EC45080011FC4A /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD565C323EC45080011FC4A /* ViewController.m */; };
|
||||
9DD565C423EC45080011FC4A /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD565C323EC45080011FC4A /* MainViewController.m */; };
|
||||
9DD565C923EC450A0011FC4A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9DD565C823EC450A0011FC4A /* Assets.xcassets */; };
|
||||
9DD565CC23EC450A0011FC4A /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9DD565CA23EC450A0011FC4A /* LaunchScreen.storyboard */; };
|
||||
9DD565CF23EC450A0011FC4A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DD565CE23EC450A0011FC4A /* main.m */; };
|
||||
|
@ -18,6 +18,8 @@
|
|||
A823321F258C3B7000C1B2D5 /* FINDemoClientHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = A823321D258C3B7000C1B2D5 /* FINDemoClientHelper.m */; };
|
||||
A863B745257A09A300959AA1 /* FINExtensionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = A863B744257A09A300959AA1 /* FINExtensionHelper.m */; };
|
||||
A8BC097A258BA095001289A3 /* FINCustomMenuModel.m in Sources */ = {isa = PBXBuildFile; fileRef = A8BC0979258BA095001289A3 /* FINCustomMenuModel.m */; };
|
||||
A8CE73562810F8C800965B7E /* FCQRCodeScanViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8CE73512810F8C800965B7E /* FCQRCodeScanViewController.m */; };
|
||||
A8CE73572810F8C800965B7E /* FCQRScanView.m in Sources */ = {isa = PBXBuildFile; fileRef = A8CE73542810F8C800965B7E /* FCQRScanView.m */; };
|
||||
FBF7F422A6EA50C856DB84F7 /* libPods-demo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 28A582EE796CD12C1FF4F5DB /* libPods-demo.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -27,8 +29,8 @@
|
|||
9DD565B923EC45080011FC4A /* demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9DD565BC23EC45080011FC4A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
9DD565BD23EC45080011FC4A /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
9DD565C223EC45080011FC4A /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
9DD565C323EC45080011FC4A /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
9DD565C223EC45080011FC4A /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = "<group>"; };
|
||||
9DD565C323EC45080011FC4A /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = "<group>"; };
|
||||
9DD565C823EC450A0011FC4A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
9DD565CB23EC450A0011FC4A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
9DD565CD23EC450A0011FC4A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
|
@ -42,6 +44,10 @@
|
|||
A863B744257A09A300959AA1 /* FINExtensionHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FINExtensionHelper.m; sourceTree = "<group>"; };
|
||||
A8BC0978258BA095001289A3 /* FINCustomMenuModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FINCustomMenuModel.h; sourceTree = "<group>"; };
|
||||
A8BC0979258BA095001289A3 /* FINCustomMenuModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FINCustomMenuModel.m; sourceTree = "<group>"; };
|
||||
A8CE73512810F8C800965B7E /* FCQRCodeScanViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FCQRCodeScanViewController.m; sourceTree = "<group>"; };
|
||||
A8CE73522810F8C800965B7E /* FCQRCodeScanViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FCQRCodeScanViewController.h; sourceTree = "<group>"; };
|
||||
A8CE73542810F8C800965B7E /* FCQRScanView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FCQRScanView.m; sourceTree = "<group>"; };
|
||||
A8CE73552810F8C800965B7E /* FCQRScanView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FCQRScanView.h; sourceTree = "<group>"; };
|
||||
FBEBA7E73B95B66C846E76FF /* Pods-demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-demo.debug.xcconfig"; path = "Target Support Files/Pods-demo/Pods-demo.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -78,16 +84,12 @@
|
|||
9DD565BB23EC45080011FC4A /* demo */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A8CE734B2810F3B400965B7E /* Common */,
|
||||
9DD565BC23EC45080011FC4A /* AppDelegate.h */,
|
||||
9DD565BD23EC45080011FC4A /* AppDelegate.m */,
|
||||
A823321E258C3B7000C1B2D5 /* FINDemoClientHelper.h */,
|
||||
A823321D258C3B7000C1B2D5 /* FINDemoClientHelper.m */,
|
||||
A863B743257A09A200959AA1 /* FINExtensionHelper.h */,
|
||||
A863B744257A09A300959AA1 /* FINExtensionHelper.m */,
|
||||
A8BC0978258BA095001289A3 /* FINCustomMenuModel.h */,
|
||||
A8BC0979258BA095001289A3 /* FINCustomMenuModel.m */,
|
||||
9DD565C223EC45080011FC4A /* ViewController.h */,
|
||||
9DD565C323EC45080011FC4A /* ViewController.m */,
|
||||
A8CE734F2810F8C800965B7E /* Scan */,
|
||||
9DD565C223EC45080011FC4A /* MainViewController.h */,
|
||||
9DD565C323EC45080011FC4A /* MainViewController.m */,
|
||||
9DD565C823EC450A0011FC4A /* Assets.xcassets */,
|
||||
9DD565CA23EC450A0011FC4A /* LaunchScreen.storyboard */,
|
||||
9DD565CD23EC450A0011FC4A /* Info.plist */,
|
||||
|
@ -99,6 +101,46 @@
|
|||
path = demo;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A8CE734B2810F3B400965B7E /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A823321E258C3B7000C1B2D5 /* FINDemoClientHelper.h */,
|
||||
A823321D258C3B7000C1B2D5 /* FINDemoClientHelper.m */,
|
||||
A863B743257A09A200959AA1 /* FINExtensionHelper.h */,
|
||||
A863B744257A09A300959AA1 /* FINExtensionHelper.m */,
|
||||
A8BC0978258BA095001289A3 /* FINCustomMenuModel.h */,
|
||||
A8BC0979258BA095001289A3 /* FINCustomMenuModel.m */,
|
||||
);
|
||||
path = Common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A8CE734F2810F8C800965B7E /* Scan */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A8CE73502810F8C800965B7E /* Controller */,
|
||||
A8CE73532810F8C800965B7E /* View */,
|
||||
);
|
||||
path = Scan;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A8CE73502810F8C800965B7E /* Controller */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A8CE73522810F8C800965B7E /* FCQRCodeScanViewController.h */,
|
||||
A8CE73512810F8C800965B7E /* FCQRCodeScanViewController.m */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A8CE73532810F8C800965B7E /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A8CE73552810F8C800965B7E /* FCQRScanView.h */,
|
||||
A8CE73542810F8C800965B7E /* FCQRScanView.m */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ACE3AE3120D1733A6BB38C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -127,7 +169,8 @@
|
|||
9DD565B523EC45080011FC4A /* Sources */,
|
||||
9DD565B623EC45080011FC4A /* Frameworks */,
|
||||
9DD565B723EC45080011FC4A /* Resources */,
|
||||
D5CFBA4174EF15FFF4AA041A /* [CP] Copy Pods Resources */,
|
||||
DFB054DF507DE3B18CCCE932 /* [CP] Embed Pods Frameworks */,
|
||||
74745716D7A4B2CB6E4BC657 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -186,7 +229,7 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
D5CFBA4174EF15FFF4AA041A /* [CP] Copy Pods Resources */ = {
|
||||
74745716D7A4B2CB6E4BC657 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
@ -203,6 +246,23 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-demo/Pods-demo-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DFB054DF507DE3B18CCCE932 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-demo/Pods-demo-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-demo/Pods-demo-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-demo/Pods-demo-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E71B82096235B4713AA534F8 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -232,10 +292,12 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9DD565C423EC45080011FC4A /* ViewController.m in Sources */,
|
||||
9DD565C423EC45080011FC4A /* MainViewController.m in Sources */,
|
||||
A823321F258C3B7000C1B2D5 /* FINDemoClientHelper.m in Sources */,
|
||||
A8BC097A258BA095001289A3 /* FINCustomMenuModel.m in Sources */,
|
||||
A8CE73562810F8C800965B7E /* FCQRCodeScanViewController.m in Sources */,
|
||||
A863B745257A09A300959AA1 /* FINExtensionHelper.m in Sources */,
|
||||
A8CE73572810F8C800965B7E /* FCQRScanView.m in Sources */,
|
||||
9DD565BE23EC45080011FC4A /* AppDelegate.m in Sources */,
|
||||
9DD565CF23EC450A0011FC4A /* main.m in Sources */,
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "ViewController.h"
|
||||
#import "MainViewController.h"
|
||||
#import "FINExtensionHelper.h"
|
||||
#import "FINDemoClientHelper.h"
|
||||
|
||||
|
@ -28,17 +28,22 @@
|
|||
NSString *bundleId = [NSBundle mainBundle].bundleIdentifier;
|
||||
NSString *path = [[NSBundle mainBundle] pathForResource:@"servers" ofType:@"plist"];
|
||||
NSDictionary *servers = [NSDictionary dictionaryWithContentsOfFile:path];
|
||||
NSDictionary *data = servers[bundleId];
|
||||
NSArray *array = servers[bundleId];
|
||||
NSMutableArray *configs = [NSMutableArray array];
|
||||
for (NSDictionary *data in array) {
|
||||
NSString *appKey = data[@"appKey"];
|
||||
NSString *appSecret = data[@"appSecret"];
|
||||
NSString *apiServer = data[@"apiServer"];
|
||||
NSString *apiPrefix = data[@"apiPrefix"];
|
||||
FATApiCryptType cryptType = [data[@"cryptType"] isEqualToString:@"MD5"] ? FATApiCryptTypeMD5 : FATApiCryptTypeSM;
|
||||
FATStoreConfig *storeConfig = [[FATStoreConfig alloc] init];
|
||||
storeConfig.sdkKey = appKey;
|
||||
storeConfig.sdkSecret = appSecret;
|
||||
storeConfig.apiServer = apiServer;
|
||||
storeConfig.cryptType = cryptType;
|
||||
[configs addObject:storeConfig];
|
||||
}
|
||||
|
||||
FATConfig *config = [FATConfig configWithAppSecret:appSecret appKey:appKey];
|
||||
config.apiServer = apiServer;
|
||||
config.apiPrefix = apiPrefix;
|
||||
config.cryptType = cryptType;
|
||||
FATConfig *config = [FATConfig configWithStoreConfigs:configs];
|
||||
[[FATClient sharedClient] initWithConfig:config error:nil];
|
||||
[[FATClient sharedClient] setEnableLog:YES];
|
||||
|
||||
|
@ -46,12 +51,16 @@
|
|||
// 注入自定义api
|
||||
[[FINExtensionHelper sharedHelper] registerCustomApis];
|
||||
|
||||
if ([bundleId isEqualToString:@"com.finogeeks.mop.finosprite"]) {
|
||||
// 该appID【wx85663af68a0cbbc8】绑定的应用为凡泰助手,若要生效,请修改BundleID为com.finogeeks.mop.finosprite
|
||||
[WXApi registerApp:@"wx85663af68a0cbbc8" universalLink:apiServer];
|
||||
[WXApi registerApp:@"wx85663af68a0cbbc8" universalLink:@"https://www.finclip.com"];
|
||||
}
|
||||
|
||||
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
||||
self.window.backgroundColor = [UIColor whiteColor];
|
||||
self.window.rootViewController = [[ViewController alloc] init];
|
||||
|
||||
MainViewController *mainVC = [[MainViewController alloc] init];
|
||||
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:mainVC];
|
||||
[self.window makeKeyAndVisible];
|
||||
|
||||
return YES;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// ViewController.h
|
||||
// MainViewController.h
|
||||
// demo
|
||||
//
|
||||
// Created by 杨涛 on 2020/2/6.
|
||||
|
@ -8,7 +8,7 @@
|
|||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface ViewController : UIViewController
|
||||
@interface MainViewController : UIViewController
|
||||
|
||||
|
||||
@end
|
|
@ -1,16 +1,18 @@
|
|||
//
|
||||
// ViewController.m
|
||||
// MainViewController.m
|
||||
// demo
|
||||
//
|
||||
// Created by 杨涛 on 2020/2/6.
|
||||
// Copyright © 2020 finogeeks. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ViewController.h"
|
||||
#import "MainViewController.h"
|
||||
#import "FCQRCodeScanViewController.h"
|
||||
|
||||
#import <FinApplet/FinApplet.h>
|
||||
#import <WechatOpenSDK/WXApi.h>
|
||||
|
||||
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
|
||||
@interface MainViewController ()<UITableViewDelegate, UITableViewDataSource>
|
||||
|
||||
@property (nonatomic, strong) UITableView *tableView;
|
||||
|
||||
|
@ -18,26 +20,29 @@
|
|||
|
||||
@end
|
||||
|
||||
@implementation ViewController
|
||||
@implementation MainViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
self.title = @"FinClip";
|
||||
|
||||
[self p_initNavigationBar];
|
||||
|
||||
[self p_loadData];
|
||||
|
||||
[self p_initSubViews];
|
||||
}
|
||||
|
||||
- (void)p_initNavigationBar {
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"扫码" style:UIBarButtonItemStylePlain target:self action:@selector(scanItemClick)];
|
||||
}
|
||||
|
||||
- (void)p_initSubViews {
|
||||
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
|
||||
CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
|
||||
|
||||
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, 44)];
|
||||
headerView.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1];
|
||||
|
||||
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, screenWidth, screenHeight) style:UITableViewStylePlain];
|
||||
self.tableView.tableHeaderView = headerView;
|
||||
self.tableView.tableFooterView = [UIView new];
|
||||
self.tableView.delegate = self;
|
||||
self.tableView.dataSource = self;
|
||||
|
@ -71,6 +76,35 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)handleQrCode:(NSString *)qrCode
|
||||
{
|
||||
NSLog(@"qrCode:%@", qrCode);
|
||||
if (![qrCode containsString:@"/runtime/applet/"]) {
|
||||
NSLog(@"不能识别的二维码");
|
||||
return;
|
||||
}
|
||||
|
||||
FATAppletQrCodeRequest *qrcodeRequest = [[FATAppletQrCodeRequest alloc] init];
|
||||
qrcodeRequest.qrCode = qrCode;
|
||||
[[FATClient sharedClient] startAppletWithQrCodeRequest:qrcodeRequest inParentViewController:self requestBlock:^(BOOL result, FATError *error) {
|
||||
NSLog(@"请求完成:%@", error);
|
||||
} completion:^(BOOL result, FATError *error) {
|
||||
NSLog(@"打开完成:%@", error);
|
||||
} closeCompletion:^{
|
||||
NSLog(@"关闭");
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - click events
|
||||
- (void)scanItemClick
|
||||
{
|
||||
FCQRCodeScanViewController *scanVC = [[FCQRCodeScanViewController alloc] init];
|
||||
scanVC.scanCompletion = ^(NSString *qrcode) {
|
||||
[self handleQrCode:qrcode];
|
||||
};
|
||||
[self.navigationController pushViewController:scanVC animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.appletList.count;
|
||||
|
@ -95,10 +129,15 @@
|
|||
NSString *appId = dict[@"appId"];
|
||||
NSDictionary *startParams = dict[@"startParams"];
|
||||
|
||||
[[FATClient sharedClient] startRemoteApplet:appId startParams:startParams InParentViewController:self completion:^(BOOL result, NSError *error) {
|
||||
if ([appId isEqualToString:@"60c5bbf99e094f00015079ee"]) {
|
||||
[self sendCustomEvent];
|
||||
}
|
||||
FATAppletRequest *request = [[FATAppletRequest alloc] init];
|
||||
request.appletId = appId;
|
||||
request.startParams = startParams;
|
||||
request.apiServer = @"https://api.finclip.com";
|
||||
|
||||
[[FATClient sharedClient] startAppletWithRequest:request InParentViewController:self completion:^(BOOL result, FATError *error) {
|
||||
|
||||
} closeCompletion:^{
|
||||
|
||||
}];
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// FCQRCodeScanViewController.h
|
||||
// FinoSprite
|
||||
//
|
||||
// Created by Haley on 2019/12/6.
|
||||
// Copyright © 2019 finogeeks. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
typedef void(^ScanCompletion)(NSString *qrcode);
|
||||
|
||||
@interface FCQRCodeScanViewController : UIViewController
|
||||
|
||||
@property (nonatomic, copy) ScanCompletion scanCompletion;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
//
|
||||
// FCQRCodeScanViewController.m
|
||||
// FinoSprite
|
||||
//
|
||||
// Created by Haley on 2019/12/6.
|
||||
// Copyright © 2019 finogeeks. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FCQRCodeScanViewController.h"
|
||||
#import "FCQRScanView.h"
|
||||
|
||||
#import <Photos/Photos.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <FinApplet/FinApplet.h>
|
||||
|
||||
@interface FCQRCodeScanViewController ()<AVCaptureMetadataOutputObjectsDelegate>
|
||||
|
||||
@property (nonatomic, strong) AVCaptureSession *session;
|
||||
|
||||
@property (nonatomic, strong) FCQRScanView *scanView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FCQRCodeScanViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view.
|
||||
|
||||
[self p_initNavigationBar];
|
||||
|
||||
[self p_addNotifications];
|
||||
|
||||
[self p_initSubView];
|
||||
|
||||
[self p_checkCameraStatus:^(BOOL granted) {
|
||||
if (granted) {
|
||||
[self p_initCameraSession];
|
||||
} else {
|
||||
[self p_showAlert:@"请在”设置-隐私-相机”选项中,允许访问你的相机" btnTitle:@"确定"];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[self p_resumeScanning];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
[self p_pauseScanning];
|
||||
}
|
||||
|
||||
#pragma mark - ovverride
|
||||
- (void)updateNavigationBar
|
||||
{
|
||||
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
|
||||
[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}];
|
||||
self.navigationController.navigationBar.barTintColor = [UIColor blackColor];
|
||||
|
||||
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
|
||||
|
||||
[self.navigationController setNavigationBarHidden:NO animated:YES];
|
||||
}
|
||||
|
||||
#pragma mark - private methods
|
||||
- (void)p_initNavigationBar
|
||||
{
|
||||
self.title = @"扫一扫";
|
||||
}
|
||||
|
||||
- (void)p_addNotifications
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive) name:UIApplicationWillResignActiveNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)p_initSubView
|
||||
{
|
||||
self.view.backgroundColor = [UIColor blackColor];
|
||||
|
||||
[self.view addSubview:self.scanView];
|
||||
}
|
||||
|
||||
- (void)p_initCameraSession
|
||||
{
|
||||
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
|
||||
if (!deviceInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
|
||||
[metadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
|
||||
// 配置扫描区域
|
||||
metadataOutput.rectOfInterest = CGRectMake(_scanView.scanner_y / self.view.frame.size.height, _scanView.scanner_x / self.view.frame.size.width, _scanView.scanner_width / self.view.frame.size.height, _scanView.scanner_width / self.view.frame.size.width);
|
||||
|
||||
self.session = [[AVCaptureSession alloc] init];
|
||||
|
||||
[self.session canSetSessionPreset:AVCaptureSessionPresetHigh];
|
||||
if ([self.session canAddInput:deviceInput]) {
|
||||
[self.session addInput:deviceInput];
|
||||
}
|
||||
|
||||
if ([self.session canAddOutput:metadataOutput]) {
|
||||
[self.session addOutput:metadataOutput];
|
||||
}
|
||||
|
||||
metadataOutput.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];
|
||||
|
||||
AVCaptureVideoPreviewLayer *videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
|
||||
videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
videoPreviewLayer.frame = self.view.layer.bounds;
|
||||
[self.view.layer insertSublayer:videoPreviewLayer atIndex:0];
|
||||
|
||||
[self.session startRunning];
|
||||
}
|
||||
|
||||
- (void)p_showAlert:(NSString *)title btnTitle:(NSString *)btnTitle
|
||||
{
|
||||
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:title style:UIAlertActionStyleCancel handler:nil];
|
||||
[alertVC addAction:cancelAction];
|
||||
[self presentViewController:alertVC animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)p_checkCameraStatus:(void (^)(BOOL granted))completion
|
||||
{
|
||||
AVAuthorizationStatus cameraStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||
|
||||
switch (cameraStatus) {
|
||||
case AVAuthorizationStatusAuthorized:
|
||||
{
|
||||
if (completion) {
|
||||
completion(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVAuthorizationStatusNotDetermined:
|
||||
{
|
||||
if (completion) {
|
||||
completion(true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (completion) {
|
||||
completion(false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// 恢复扫一扫功能
|
||||
- (void)p_resumeScanning
|
||||
{
|
||||
[self.session startRunning];
|
||||
[self.scanView p_startScannerLineAnimation];
|
||||
}
|
||||
|
||||
/// 暂停扫一扫功能
|
||||
- (void)p_pauseScanning
|
||||
{
|
||||
[self.session stopRunning];
|
||||
[self.scanView p_pauseScannerLineAnimation];
|
||||
}
|
||||
|
||||
#pragma mark - QRCode handler
|
||||
- (void)handleQrCode:(NSString *)qrCode
|
||||
{
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
|
||||
if (self.scanCompletion) {
|
||||
self.scanCompletion(qrCode);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - notification handler
|
||||
- (void)appDidBecomeActive
|
||||
{
|
||||
[self p_resumeScanning];
|
||||
}
|
||||
|
||||
- (void)appWillResignActive
|
||||
{
|
||||
[self p_pauseScanning];
|
||||
}
|
||||
|
||||
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
|
||||
-(void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
if (metadataObjects != nil && metadataObjects.count > 0) {
|
||||
|
||||
[self p_pauseScanning];
|
||||
|
||||
AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
|
||||
[self handleQrCode:[obj stringValue]];
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - setter && getter
|
||||
|
||||
- (FCQRScanView *)scanView
|
||||
{
|
||||
if (!_scanView) {
|
||||
_scanView = [[FCQRScanView alloc] initWithFrame:self.view.bounds];
|
||||
}
|
||||
return _scanView;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@end
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// FCQRScanView.h
|
||||
// FinoSprite
|
||||
//
|
||||
// Created by Haley on 2019/12/6.
|
||||
// Copyright © 2019 finogeeks. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface FCQRScanView : UIView
|
||||
|
||||
@property (nonatomic, assign) CGFloat scanner_width;
|
||||
@property (nonatomic, assign) CGFloat scanner_x;
|
||||
@property (nonatomic, assign) CGFloat scanner_y;
|
||||
|
||||
- (void)p_startScannerLineAnimation;
|
||||
|
||||
- (void)p_pauseScannerLineAnimation;
|
||||
|
||||
- (void)p_addActivityIndicator;
|
||||
|
||||
- (void)p_removeActivityIndicator;
|
||||
|
||||
@end
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
//
|
||||
// FCQRScanView.m
|
||||
// FinoSprite
|
||||
//
|
||||
// Created by Haley on 2019/12/6.
|
||||
// Copyright © 2019 finogeeks. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FCQRScanView.h"
|
||||
|
||||
const CGFloat scanner_borderWidth = 1.0; /** 扫描器边框宽度 */
|
||||
const CGFloat scanner_cornerWidth = 3.0; /** 扫描器棱角宽度 */
|
||||
const CGFloat scanner_cornerLength = 20.0; /** 扫描器棱角长度 */
|
||||
const CGFloat scanner_lineHeight = 1.0; /** 扫描器线条高度 */
|
||||
const CGFloat tipLab_height = 50.0; /** 扫描器下方提示文字高度 */
|
||||
|
||||
static NSString *scannerLineAnmationKey = @"ScannerLineAnmationKey"; /** 扫描线条动画Key值 */
|
||||
|
||||
@interface FCQRScanView ()
|
||||
|
||||
@property (nonatomic, strong) UIColor *scannerBorderColor;
|
||||
|
||||
@property (nonatomic, strong) UIColor *scannerCornerColor;
|
||||
|
||||
@property (nonatomic, strong) UIImageView *scannerLine;
|
||||
|
||||
@property (nonatomic, strong) UILabel *tipLabel;
|
||||
|
||||
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FCQRScanView
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
{
|
||||
self = [super initWithFrame:frame];
|
||||
if (self) {
|
||||
_scanner_width = 0.7 * frame.size.width;
|
||||
_scanner_x = (frame.size.width - _scanner_width) / 2;
|
||||
_scanner_y = 100;
|
||||
|
||||
_scannerBorderColor = [UIColor whiteColor];
|
||||
_scannerCornerColor = [UIColor colorWithRed:66/255.0f green:134/255.0 blue:246/255.0 alpha:1.0];
|
||||
|
||||
[self p_initSubViews];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)p_initSubViews
|
||||
{
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
|
||||
[self addSubview:self.scannerLine];
|
||||
|
||||
[self addSubview:self.tipLabel];
|
||||
}
|
||||
|
||||
|
||||
- (void)p_startScannerLineAnimation
|
||||
{
|
||||
[self.scannerLine.layer removeAllAnimations];
|
||||
|
||||
CABasicAnimation *lineAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
|
||||
lineAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0, _scanner_width - scanner_lineHeight, 1)];
|
||||
lineAnimation.duration = 4;
|
||||
lineAnimation.repeatCount = MAXFLOAT;
|
||||
[self.scannerLine.layer addAnimation:lineAnimation forKey:scannerLineAnmationKey];
|
||||
// 重置动画运行速度为1.0
|
||||
self.scannerLine.layer.speed = 1.0;
|
||||
}
|
||||
|
||||
- (void)p_pauseScannerLineAnimation
|
||||
{
|
||||
// 取出当前时间,转成动画暂停的时间
|
||||
CFTimeInterval pauseTime = [self.scannerLine.layer convertTime:CACurrentMediaTime() fromLayer:nil];
|
||||
// 设置动画的时间偏移量,指定时间偏移量的目的是让动画定格在该时间点的位置
|
||||
self.scannerLine.layer.timeOffset = pauseTime;
|
||||
// 将动画的运行速度设置为0, 默认的运行速度是1.0
|
||||
self.scannerLine.layer.speed = 0;
|
||||
}
|
||||
|
||||
- (void)p_addActivityIndicator
|
||||
{
|
||||
if (!_activityIndicator) {
|
||||
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
_activityIndicator.center = self.center;
|
||||
[self addSubview:_activityIndicator];
|
||||
}
|
||||
|
||||
[_activityIndicator startAnimating];
|
||||
}
|
||||
|
||||
- (void)p_removeActivityIndicator
|
||||
{
|
||||
if (_activityIndicator) {
|
||||
[_activityIndicator removeFromSuperview];
|
||||
_activityIndicator = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect
|
||||
{
|
||||
[super drawRect:rect];
|
||||
|
||||
// 半透明区域
|
||||
[[UIColor colorWithWhite:0 alpha:0.7] setFill];
|
||||
UIRectFill(rect);
|
||||
|
||||
// 透明区域
|
||||
CGRect scanner_rect = CGRectMake(_scanner_x, _scanner_y, _scanner_width, _scanner_width);
|
||||
[[UIColor clearColor] setFill];
|
||||
UIRectFill(scanner_rect);
|
||||
|
||||
// 边框
|
||||
UIBezierPath *borderPath = [UIBezierPath bezierPathWithRect:CGRectMake(_scanner_x, _scanner_y, _scanner_width, _scanner_width)];
|
||||
borderPath.lineCapStyle = kCGLineCapRound;
|
||||
borderPath.lineWidth = scanner_borderWidth;
|
||||
[_scannerBorderColor set];
|
||||
[borderPath stroke];
|
||||
|
||||
for (int index = 0; index < 4; index++) {
|
||||
UIBezierPath *tempPath = [UIBezierPath bezierPath];
|
||||
tempPath.lineWidth = scanner_cornerWidth;
|
||||
[_scannerCornerColor set];
|
||||
switch (index) {
|
||||
// 左上角
|
||||
case 0:
|
||||
[tempPath moveToPoint:CGPointMake(_scanner_x + scanner_cornerLength, _scanner_y)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x, _scanner_y)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x, _scanner_y + scanner_cornerLength)];
|
||||
break;
|
||||
// 右上角
|
||||
case 1:
|
||||
[tempPath moveToPoint:CGPointMake(_scanner_x + _scanner_width - scanner_cornerLength, _scanner_y)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x + _scanner_width, _scanner_y)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x + _scanner_width, _scanner_y + scanner_cornerLength)];
|
||||
break;
|
||||
// 左下角
|
||||
case 2:
|
||||
[tempPath moveToPoint:CGPointMake(_scanner_x, _scanner_y + _scanner_width - scanner_cornerLength)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x, _scanner_y + _scanner_width)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x + scanner_cornerLength, _scanner_y + _scanner_width)];
|
||||
break;
|
||||
// 右下角
|
||||
case 3:
|
||||
[tempPath moveToPoint:CGPointMake(_scanner_x + _scanner_width - scanner_cornerLength, _scanner_y + _scanner_width)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x + _scanner_width, _scanner_y + _scanner_width)];
|
||||
[tempPath addLineToPoint:CGPointMake(_scanner_x + _scanner_width, _scanner_y + _scanner_width - scanner_cornerLength)];
|
||||
break;
|
||||
}
|
||||
[tempPath stroke];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (UIImage *)fin_imageWithColor:(UIColor *)color
|
||||
{
|
||||
CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); //宽高 1.0只要有值就够了
|
||||
UIGraphicsBeginImageContext(rect.size); //在这个范围内开启一段上下文
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
|
||||
CGContextSetFillColorWithColor(context, [color CGColor]);//在这段上下文中获取到颜色UIColor
|
||||
CGContextFillRect(context, rect);//用这个颜色填充这个上下文
|
||||
|
||||
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();//从这段上下文中获取Image属性,,,结束
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#pragma mark - setter && getter
|
||||
- (UIImageView *)scannerLine
|
||||
{
|
||||
if (!_scannerLine) {
|
||||
_scannerLine = [[UIImageView alloc] initWithFrame:CGRectMake(_scanner_x + 5, _scanner_y, _scanner_width - 10, scanner_lineHeight)];
|
||||
UIColor *tinColor = [UIColor colorWithRed:66/255.0f green:134/255.0 blue:246/255.0 alpha:1.0];
|
||||
_scannerLine.image = [self fin_imageWithColor:tinColor];
|
||||
}
|
||||
|
||||
return _scannerLine;
|
||||
}
|
||||
|
||||
- (UILabel *)tipLabel
|
||||
{
|
||||
if (!_tipLabel) {
|
||||
_tipLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, _scanner_y + _scanner_width, self.frame.size.width, 50)];
|
||||
_tipLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_tipLabel.textColor = [UIColor lightGrayColor];
|
||||
_tipLabel.font = [UIFont systemFontOfSize:13];
|
||||
_tipLabel.text = @"将二维码放入框内,即可自动扫描";
|
||||
}
|
||||
return _tipLabel;
|
||||
}
|
||||
|
||||
@end
|
|
@ -3,6 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.finogeeks.finclip.demo</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>appKey</key>
|
||||
<string>22LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=</string>
|
||||
|
@ -10,12 +11,22 @@
|
|||
<string>bdfd76cae24d4313</string>
|
||||
<key>apiServer</key>
|
||||
<string>https://api.finclip.com</string>
|
||||
<key>apiPrefix</key>
|
||||
<string>/api/v1/mop/</string>
|
||||
<key>cryptType</key>
|
||||
<string>MD5</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>appKey</key>
|
||||
<string>22LyZEib0gLTQdU3MUauAUJPk2mIMV4Hq+tBzQxTSqhndG2JOPsS9yA5fww36gSp</string>
|
||||
<key>appSecret</key>
|
||||
<string>1e9b3d1693d06fa1</string>
|
||||
<key>apiServer</key>
|
||||
<string>https://finclip-testing.finogeeks.club</string>
|
||||
<key>cryptType</key>
|
||||
<string>SM</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>com.finogeeks.mop.finosprite</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>appKey</key>
|
||||
<string>22LyZEib0gLTQdU3MUauAQVLIkNNhTSGIN42gXzlAsk=</string>
|
||||
|
@ -23,10 +34,9 @@
|
|||
<string>ae55433be2f62915</string>
|
||||
<key>apiServer</key>
|
||||
<string>https://finchat-mop-b.finogeeks.club</string>
|
||||
<key>apiPrefix</key>
|
||||
<string>/api/v1/mop/</string>
|
||||
<key>cryptType</key>
|
||||
<string>SM</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Loading…
Reference in New Issue