Compare commits

..

No commits in common. "phiz_2.45.7.2" and "master" have entirely different histories.

167 changed files with 209 additions and 10635 deletions

View File

@ -82,24 +82,19 @@ class _MyAppState extends State<MyApp> {
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> init() async {
//
FinStoreConfig storeConfigA = FinStoreConfig(
"22LyZEib0gLTQdU3MUauAfJ/xujwNfM6OvvEqQyH4igA",
"703b9026be3d6bc5",
"https://api.finclip.com",
cryptType: "SM",
);
List<FinStoreConfig> storeConfigs = [storeConfigA];
Config config = Config(storeConfigs);
config.language = LanguageType.English;
config.userId = "abc12345";
config.channel = "finclip";
config.phone = "12345678901";
config.appletDebugMode = BOOLState.BOOLStateTrue;
UIConfig uiconfig = UIConfig();
uiconfig.isHideBackHome = true;
final res = await Mop.instance.initSDK(config, uiConfig: uiconfig);
if (Platform.isiOS) {
//com.finogeeks.mopExample
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
print(res);
} else if (Platform.isAndroid) {
//com.finogeeks.mopexample
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARjmmp6QmYgjGb3uHueys1oA', '98c49f97a031b555',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
print(res);
}
if (!mounted) return;
}
@ -175,29 +170,24 @@ class _MyAppState extends State<MyApp> {
使 SDK API SDK SDK
```
///
/// initialize FinClip SDK.
/// SDK(使)
/// [config] is required. sdk
/// [uiConfig] is optional. UI
Future<Map> initSDK(Config config, {UIConfig? uiConfig})
///
/// initialize mop miniprogram engine.
///
/// [appkey] is required. it can be getted from api.finclip.com
/// [secret] is required. it can be getted from api.finclip.com
/// [apiServer] is optional. the mop server address. default is https://mp.finogeek.com
/// [apiPrefix] is optional. the mop server prefix. default is /api/v1/mop
///
///
Future<Map> initialize(String appkey, String secret,
{String apiServer, String apiPrefix})
```
使
```
// 1.Config
// 1.1 1
FinStoreConfig finclip_store = FinStoreConfig('22LyZEib0gLTQdU3MUauATBwgfnTCJjdr7FCnywmAEM=', 'bdfd76cae24d4313', 'https://api.finclip.com');
// 1.2 2
FinStoreConfig test_store = FinStoreConfig('sdkKey2', 'sdkSecret2', '测试服务器');
Config config = Config([finclip_store, test_store]);
config.userId = '您app的用户唯一标识';
// 2.UIConfig
UIConfig uiConfig = UIConfig();
uiConfig.isHideAddToDesktopMenu = true;
uiConfig.isHideFeedbackAndComplaints = true;
final res = await Mop.instance.initSDK(config, uiConfig: uiConfig);
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
```
### 2.

View File

@ -1,11 +1,11 @@
arguments=--init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
arguments=--init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(7.4.2))
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true

View File

@ -91,6 +91,6 @@ kapt {
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.finogeeks.lib:finapplet:2.45.7'
implementation 'com.finogeeks.mop:plugins:2.45.7'
implementation 'com.finogeeks.lib:finapplet:2.41.11'
implementation 'com.finogeeks.mop:plugins:2.41.11'
}

View File

@ -1,46 +0,0 @@
// The code is already well written and doesn't need any improvement.
// However, I will add some comments to make it more readable.
package com.finogeeks.mop.api;
import android.content.Context;
import androidx.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
public abstract class SyncApi extends BaseApi {
public SyncApi(Context context) {
super(context);
}
// This method is used to invoke the API.
@Nullable
public abstract String invoke(String url, JSONObject jsonObject);
// This method is used to get the success response.
public JSONObject getSuccessRes(String message) {
JSONObject jsonObject = new JSONObject();
String key = "errMsg";
try {
jsonObject.put(key, message + ":ok");
return jsonObject;
} catch (JSONException e) {
e.printStackTrace();
return jsonObject;
}
}
// This method is used to get the failure response.
public String getFailureRes(String message, String error) {
JSONObject jsonObject = new JSONObject();
String key = "errMsg";
try {
return jsonObject.put(key, message + ":fail " + error).toString();
} catch (JSONException e) {
e.printStackTrace();
return "{\"errMsg\":" + message + "\":fail \"" + error + "}";
}
}
}

View File

@ -95,7 +95,7 @@ public class AppletManageModule extends BaseApi {
callback.onFail(null);
}
} else if (event.equals("clearApplets")) {
FinAppClient.INSTANCE.getAppletApiManager().finishAllRunningApplets();
FinAppClient.INSTANCE.getAppletApiManager().clearApplets();
callback.onSuccess(null);
} else if (event.equals("removeUsedApplet")) {
Log.d("MopPlugin", "removeUsedApplet:params:" + param);

View File

@ -4,10 +4,9 @@ import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import com.finogeeks.lib.applet.client.FinAppClient;
import com.finogeeks.lib.applet.client.FinAppInfo;
import com.finogeeks.lib.applet.interfaces.FinCallback;
import com.finogeeks.lib.applet.client.FinAppInfo;
import com.finogeeks.lib.applet.sdk.api.request.IFinAppletRequest;
import com.finogeeks.lib.applet.sdk.model.StartAppletDecryptRequest;
import com.finogeeks.mop.api.BaseApi;
@ -65,19 +64,6 @@ public class AppletModule extends BaseApi {
Map<String, String> params = (Map) param.get("params");
String apiServer = (String) param.get("apiServer");
Boolean isSingleProcess = (Boolean) param.get("isSingleProcess");
Boolean isSingTask = (Boolean) param.get("isSingTask");
IFinAppletRequest.ProcessMode processMode;
if (Boolean.TRUE.equals(isSingleProcess)) {
processMode = IFinAppletRequest.ProcessMode.SINGLE;
} else {
processMode = IFinAppletRequest.ProcessMode.MULTI;
}
IFinAppletRequest.TaskMode taskMode;
if (Boolean.TRUE.equals(isSingTask)) {
taskMode = IFinAppletRequest.TaskMode.SINGLE;
} else {
taskMode = IFinAppletRequest.TaskMode.MULTI;
}
// mContextFlutterActivity
// Android 6.07.0contextmContext
// 使Application Context
@ -90,9 +76,7 @@ public class AppletModule extends BaseApi {
IFinAppletRequest.Companion.fromAppId(apiServer, appId)
.setStartParams(startParams)
.setSequence(sequence)
.setProcessMode(processMode)
.setTaskMode(taskMode)
,
.setSingleProcess(Boolean.TRUE.equals(isSingleProcess)),
null
);
// FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, apiServer, appId, sequence, startParams,null);
@ -101,7 +85,7 @@ public class AppletModule extends BaseApi {
IFinAppletRequest.Companion.fromAppId(appId)
.setStartParams(startParams)
.setSequence(sequence)
.setProcessMode(processMode),
.setSingleProcess(Boolean.TRUE.equals(isSingleProcess)),
null
);
}
@ -164,21 +148,8 @@ public class AppletModule extends BaseApi {
String offlineMiniprogramZipPath = (String) param.get("offlineMiniprogramZipPath");
String offlineFrameworkZipPath = (String) param.get("offlineFrameworkZipPath");
Boolean isSingleProcess = (Boolean) param.get("isSingleProcess");
Boolean isSingTask = (Boolean) param.get("isSingTask");
IFinAppletRequest.ProcessMode processMode;
if (Boolean.TRUE.equals(isSingleProcess)) {
processMode = IFinAppletRequest.ProcessMode.SINGLE;
} else {
processMode = IFinAppletRequest.ProcessMode.MULTI;
}
IFinAppletRequest.TaskMode taskMode;
if (Boolean.TRUE.equals(isSingTask)) {
taskMode = IFinAppletRequest.TaskMode.SINGLE;
} else {
taskMode = IFinAppletRequest.TaskMode.MULTI;
}
IFinAppletRequest.ReLaunchMode mode = getReLaunchMode(param);
Log.d("MopPlugin", "startApplet (appId=" + appId + ", sequence=" + sequence + ", apiServer=" + apiServer + ", isSingleProcess:" + isSingleProcess);
Log.d("MopPlugin", "startApplet (appId=" + appId + ", sequence=" + sequence + " apiServer=" + apiServer + ")");
// mContextFlutterActivity
// Android 6.07.0contextmContext
// 使Application Context
@ -192,9 +163,7 @@ public class AppletModule extends BaseApi {
.setSequence(sequence)
.setStartParams(params)
.setOfflineParams(offlineFrameworkZipPath, offlineMiniprogramZipPath)
.setProcessMode(processMode)
.setTaskMode(taskMode)
.setReLaunchMode(mode),
.setSingleProcess(Boolean.TRUE.equals(isSingleProcess)),
null);
// request
// FinAppClient.INSTANCE.getAppletApiManager().startApplet(context, IFinAppletRequest.Companion.fromAppId("apiServer", "appId")
@ -205,44 +174,17 @@ public class AppletModule extends BaseApi {
private void scanOpenApplet(Map param, ICallback callback) {
String info = String.valueOf(param.get("info"));
Boolean isSingleProcess = (Boolean) param.get("isSingleProcess");
Boolean isSingTask = (Boolean) param.get("isSingTask");
IFinAppletRequest.ProcessMode processMode;
if (Boolean.TRUE.equals(isSingleProcess)) {
processMode = IFinAppletRequest.ProcessMode.SINGLE;
} else {
processMode = IFinAppletRequest.ProcessMode.MULTI;
}
IFinAppletRequest.TaskMode taskMode;
if (Boolean.TRUE.equals(isSingTask)) {
taskMode = IFinAppletRequest.TaskMode.SINGLE;
} else {
taskMode = IFinAppletRequest.TaskMode.MULTI;
}
FinAppClient.INSTANCE.getAppletApiManager().startApplet(mContext, IFinAppletRequest.Companion.fromDecrypt(info)
.setProcessMode(processMode).setTaskMode(taskMode), null);
.setSingleProcess(Boolean.TRUE.equals(isSingleProcess)), null);
// FinAppClient.INSTANCE.getAppletApiManager().startApplet(mContext, new StartAppletDecryptRequest(info),null);
callback.onSuccess(new HashMap());
}
private void qrcodeOpenApplet(Map param, ICallback callback) {
private void qrcodeOpenApplet(Map param, ICallback callback){
String qrcode = String.valueOf(param.get("qrcode"));
Boolean isSingleProcess = (Boolean) param.get("isSingleProcess");
Boolean isSingTask = (Boolean) param.get("isSingTask");
IFinAppletRequest.ProcessMode processMode;
if (Boolean.TRUE.equals(isSingleProcess)) {
processMode = IFinAppletRequest.ProcessMode.SINGLE;
} else {
processMode = IFinAppletRequest.ProcessMode.MULTI;
}
IFinAppletRequest.TaskMode taskMode;
if (Boolean.TRUE.equals(isSingTask)) {
taskMode = IFinAppletRequest.TaskMode.SINGLE;
} else {
taskMode = IFinAppletRequest.TaskMode.MULTI;
}
IFinAppletRequest.ReLaunchMode mode = getReLaunchMode(param);
FinAppClient.INSTANCE.getAppletApiManager().startApplet(mContext, IFinAppletRequest.Companion.fromQrCode(qrcode)
.setProcessMode(processMode).setTaskMode(taskMode).setReLaunchMode(mode), new FinCallback<String>() {
.setSingleProcess(Boolean.TRUE.equals(isSingleProcess)), new FinCallback<String>() {
@Override
public void onSuccess(String s) {
callback.onSuccess(new HashMap());
@ -280,25 +222,6 @@ public class AppletModule extends BaseApi {
});*/
}
@NonNull
private static IFinAppletRequest.ReLaunchMode getReLaunchMode(Map param) {
IFinAppletRequest.ReLaunchMode mode = IFinAppletRequest.ReLaunchMode.PARAMS_EXIST;
Object modeValue = param.get("reLaunchMode");
if (modeValue != null) {
if (modeValue instanceof Integer) {
int reLaunchMode = (Integer) modeValue;
if (reLaunchMode == 1) {
mode = IFinAppletRequest.ReLaunchMode.ONLY_PARAMS_DIFF;
} else if (reLaunchMode == 2) {
mode = IFinAppletRequest.ReLaunchMode.ALWAYS;
} else if (reLaunchMode == 3) {
mode = IFinAppletRequest.ReLaunchMode.NEVER;
}
}
}
return mode;
}
private void changeUserId(Map param, ICallback callback) {
String userId = String.valueOf(param.get("userId"));
if (FinAppClient.INSTANCE.getFinAppConfig() != null) {
@ -312,4 +235,4 @@ public class AppletModule extends BaseApi {
});
}
}
}
}

View File

@ -33,7 +33,7 @@ public class ExtensionApiModule extends BaseApi {
@Override
public String[] apis() {
return new String[]{"registerExtensionApi","registerSyncExtensionApi","addWebExtentionApi"};
return new String[]{"registerExtensionApi","addWebExtentionApi"};
}
@Override
@ -87,63 +87,6 @@ public class ExtensionApiModule extends BaseApi {
iCallback.onFail();
}
@Override
public void notImplemented() {
iCallback.onFail();
}
});
});
}
});
} else if (s.equals("registerSyncExtensionApi")) {
MethodChannel channel = MopPluginService.getInstance().getMethodChannel();
String name = (String) param.get("name");
Log.d(TAG, "registerSyncExtensionApi:" + name);
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new com.finogeeks.lib.applet.api.BaseApi(getContext()) {
@Override
public String[] apis() {
return new String[]{name};
}
@Override
public void invoke(String s, JSONObject jsonObject, com.finogeeks.lib.applet.interfaces.ICallback iCallback) {
Log.d("MopPlugin", "sync invoke extensionApi:" + s + ",params:" + jsonObject);
Map params = GsonUtil.gson.fromJson(jsonObject.toString(), HashMap.class);
handler.post(() -> {
channel.invokeMethod("syncextensionapi:" + name, params, new MethodChannel.Result() {
@Override
public void success(Object result) {
String json = GsonUtil.gson.toJson(result);
Log.d(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " success, result=" + result + ", json=" + json);
JSONObject ret = null;
if (json != null && !json.equals("null")) {
try {
ret = new JSONObject(json);
if (ret.has("errMsg")) {
String errMsg = ret.getString("errMsg");
if (errMsg.startsWith(name + ":fail")) {
iCallback.onFail(ret);
return;
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
iCallback.onSuccess(ret);
}
@Override
public void error(String errorCode, String errorMessage, Object errorDetails) {
FLog.e(ExtensionApiModule.TAG, "channel invokeMethod:" + name
+ " error, errorCode=" + errorCode
+ ", errorMessage=" + errorMessage
+ ", errorDetails=" + errorDetails);
iCallback.onFail();
}
@Override
public void notImplemented() {
iCallback.onFail();

View File

@ -80,15 +80,6 @@ public class InitSDKModule extends BaseApi {
if (userId != null) {
configBuilder.setUserId(userId);
}
String channel = (String) configMap.get("channel");
if (channel != null) {
configBuilder.setChannel(channel);
}
String phone = (String) configMap.get("phone");
if (phone != null) {
configBuilder.setPhone(phone);
}
String productIdentification = (String) configMap.get("productIdentification");
if (productIdentification != null) {
configBuilder.setProductIdentification(productIdentification);
@ -142,17 +133,10 @@ public class InitSDKModule extends BaseApi {
configBuilder.setSchemes(schemes);
}
configBuilder.setDebugMode((Boolean) configMap.get("debug"));
configBuilder.setEnableLog((Boolean) configMap.get("debug"));
Integer maxRunningApplet = (Integer) configMap.get("maxRunningApplet");
if (maxRunningApplet != null) {
configBuilder.setMaxRunningApplet(maxRunningApplet);
}
Integer backgroundFetchPeriod = (Integer) configMap.get("backgroundFetchPeriod");
if (backgroundFetchPeriod != null) {
configBuilder.setBackgroundFetchPeriod(backgroundFetchPeriod);
}
Integer webViewMixedContentMode = (Integer) configMap.get("webViewMixedContentMode");
if (webViewMixedContentMode != null) {
configBuilder.setWebViewMixedContentMode(webViewMixedContentMode);
@ -164,7 +148,6 @@ public class InitSDKModule extends BaseApi {
}
configBuilder.setMinAndroidSdkVersion((Integer) configMap.get("minAndroidSdkVersion"));
configBuilder.setEnableScreenShot((Boolean) configMap.get("enableScreenShot"));
configBuilder.setDisableTbs(true);
int screenShotPriorityIndex = (Integer) configMap.get("screenShotPriority");
if (screenShotPriorityIndex == 0) {
configBuilder.setScreenShotPriority(FinAppConfigPriority.GLOBAL);
@ -211,23 +194,11 @@ public class InitSDKModule extends BaseApi {
if (appletText != null) {
configBuilder.setAppletText(appletText);
}
Object localeLanguage = configMap.get("localeLanguage");
if (localeLanguage != null) {
String language = (String) localeLanguage;
if (language.contains("_")) {
String[] locales = language.split("_");
configBuilder.setLocale(new Locale(locales[0], locales[1]));
} else {
configBuilder.setLocale(new Locale(language));
}
Integer languageInteger = (Integer) configMap.get("language");
if (languageInteger == 1) {
configBuilder.setLocale(Locale.ENGLISH);
} else {
Integer languageInteger = (Integer) configMap.get("language");
if (languageInteger == 1) {
configBuilder.setLocale(Locale.ENGLISH);
} else {
configBuilder.setLocale(Locale.SIMPLIFIED_CHINESE);
}
configBuilder.setLocale(Locale.SIMPLIFIED_CHINESE);
}
// uiConfig

View File

@ -2,7 +2,7 @@ package com.finogeeks.mop.api.mop;
import android.content.Context;
import com.finogeeks.finclip.sdkcore.manager.FinClipSDKCoreManager;
import com.finogeeks.finochat.sdkcore.client.FinoChatSDKCoreClient;
import com.finogeeks.lib.applet.client.FinAppClient;
import com.finogeeks.lib.applet.db.entity.FinApplet;
import com.finogeeks.mop.api.BaseApi;
@ -25,7 +25,7 @@ public class SmSignModule extends BaseApi {
@Override
public void invoke(String event, Map param, ICallback callback) {
String text = (String) param.get("plainText");
String result = new FinClipSDKCoreManager.Builder().build().messageDigestBySM(text);
String result = FinoChatSDKCoreClient.getInstance().finoLicenseService().messageDigest(text);
Map<String, Object> res = new HashMap<>();
res.put("data", result);
callback.onSuccess(res);

View File

@ -39,7 +39,6 @@ public class InitUtils {
uiConfig.setHideShareAppletMenu((Boolean) map.get("isHideShareAppletMenu"));
uiConfig.setHideAddToDesktopMenu((Boolean) map.get("isHideAddToDesktopMenu"));
uiConfig.setHideFavoriteMenu((Boolean) map.get("isHideFavoriteMenu"));
uiConfig.setHideClearCacheMenu((Boolean) map.get("isHideClearCacheMenu"));
uiConfig.setHideSettingMenu((Boolean) map.get("isHideSettingMenu"));
uiConfig.setHideTransitionCloseButton((Boolean) map.get("hideTransitionCloseButton"));
uiConfig.setUseNativeLiveComponent((Boolean) map.get("useNativeLiveComponent"));

View File

@ -1,68 +0,0 @@
export LANG=en_US.UTF-8
export FASTLANE_DISABLE_COLORS=1
export version="$1"
export iosVersion="$2"
export androidVersion="$3"
#version=`git describe --abbrev=0 --tags | tr -d '\\n' | tr -d '\\t'`
echo "当前版本号:${version}"
echo "依赖的iOS${iosVersion}"
echo "依赖的Android:${androidVersion}"
#git reset --hard
#git checkout ${version}
# pubspec.yaml
cp -r pubspec.tpl.yaml pubspec.yaml
sed -i "" "s/__mop_flutter_sdk_version__/${version}/g" pubspec.yaml
# iOS podspec
if [ -n "$iosVersion" ]
then
echo "更新mop.podspec====>"
cp -r ios/mop.podspec.tpl ios/mop.podspec
sed -i "" "s/__finapplet_version__/${iosVersion}/g" ios/mop.podspec
fi
# android gradle
if [ -n "$androidVersion" ]
then
echo "更新build.gradle====>"
cp -r android/build.gradle.tpl android/build.gradle
sed -i "" "s/__finapplet_version__/${androidVersion}/g" android/build.gradle
fi
cat pubspec.yaml
git remote add ssh-origin ssh://git@gitlab.finogeeks.club:2233/finclipsdk/finclip-flutter-sdk.git
git add .
git commit -m "release: version:$version"
git tag -d ${version}
git push ssh-origin --delete tag ${version}
git tag -a ${version} -m 'FinClip-Flutter-SDK发版'
git push ssh-origin HEAD:refs/heads/master --tags -f
#export http_proxy=http://127.0.0.1:1087
#export https_proxy=http://127.0.0.1:1087
flutter packages pub publish --dry-run --server=https://pub.dartlang.org
flutter packages pub publish --server=https://pub.dartlang.org --force
#unset http_proxy
#unset https_proxy
git remote add github ssh://git@github.com/finogeeks/mop-flutter-sdk.git
#git push github HEAD:refs/heads/master --tags
git push github HEAD:refs/heads/master

View File

@ -1,11 +1,11 @@
arguments=--init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tx/98mydjws12b717spn4mx1wd80000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
arguments=--init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/d146c9752a26f79b52047fb6dc6ed385d064e120494f96f08ca63a317c41f94c.gradle --init-script /var/folders/tv/dbm7kt650fvdxrtf0k7xgxcm0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
java.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true

View File

@ -70,7 +70,7 @@ flutter {
}
dependencies {
def sdk_version = "2.45.1"
compileOnly "com.finogeeks.lib:finapplet:${sdk_version}"
def sdk_version = "2.41.3"
compileOnly "com.finogeeks.lib:finapplet:2.41.4-dev20230721v13"
implementation "com.finogeeks.mop:plugins:${sdk_version}"
}

View File

@ -1,11 +1,11 @@
PODS:
- FinApplet (2.45.1)
- FinAppletExt (2.45.1):
- FinApplet (= 2.45.1)
- FinApplet (2.40.12-dev20230615v03)
- FinAppletExt (2.40.12-dev20230615v03):
- FinApplet (= 2.40.12-dev20230615v03)
- Flutter (1.0.0)
- mop (0.1.1):
- FinApplet (= 2.45.1)
- FinAppletExt (= 2.45.1)
- FinApplet (= 2.40.12-dev20230615v03)
- FinAppletExt (= 2.40.12-dev20230615v03)
- Flutter
DEPENDENCIES:
@ -13,7 +13,7 @@ DEPENDENCIES:
- mop (from `.symlinks/plugins/mop/ios`)
SPEC REPOS:
ssh://gitlab.finogeeks.club/finclip-ios/FinPods:
ssh://gitlab.finogeeks.club/finclip-ios/DevPods:
- FinApplet
- FinAppletExt
@ -24,11 +24,11 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/mop/ios"
SPEC CHECKSUMS:
FinApplet: eea27894485c871a94b2ded79a8fe1e84d7ffcc9
FinAppletExt: 231dde4c4ed3862b70179c3dfac7406090ace955
FinApplet: 8c14ee57dcefca25074fc4ae5ff047d0636d9116
FinAppletExt: b6356d98e0897017611a402aaf97f24686652d93
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
mop: afa40651ec188a85a27c068d5afa2a97c6a53a01
mop: 2610a14e951144088f87aea5881db9c5d58a5995
PODFILE CHECKSUM: 2da0220ee5ba22a2dfcec42dfe5b17d05f3c3da9
COCOAPODS: 1.15.2
COCOAPODS: 1.11.3

View File

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
@ -367,7 +367,6 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = finclip_example;
@ -378,7 +377,6 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite;
PRODUCT_NAME = "$(TARGET_NAME)";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
@ -497,10 +495,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4;
DEVELOPMENT_TEAM = 9QCKYFU5M4;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = finclip_example;
@ -511,8 +507,6 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@ -526,10 +520,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 9QCKYFU5M4;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 9QCKYFU5M4;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = finclip_example;
@ -540,7 +532,6 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.finogeeks.finosprite;
PRODUCT_NAME = "$(TARGET_NAME)";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = wild_all;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -1,11 +1,13 @@
// ignore_for_file: prefer_const_constructors
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mop/api.dart';
import 'dart:async';
import 'dart:io';
import 'package:mop/mop.dart';
import 'package:mop_example/test_page.dart';
void main() => runApp(MyApp());
@ -20,10 +22,7 @@ class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 3), () {
init();
});
init();
}
// Platform messages are asynchronous, so we initialize in an async method.
@ -46,9 +45,6 @@ class _MyAppState extends State<MyApp> {
Config config = Config(storeConfigs);
config.language = LanguageType.English;
config.baseLoadingViewClass = "LoadingView";
config.userId = "18607180143";
config.channel = "finclip";
config.phone = "1234567890";
config.appletDebugMode = BOOLState.BOOLStateTrue;
UIConfig uiconfig = UIConfig();
@ -87,26 +83,9 @@ class _MyAppState extends State<MyApp> {
Mop.instance.registerExtensionApi('getUserProfile', getUserProfile);
Mop.instance.registerExtensionApi('pushNativePage', pushNativePage);
if (!mounted) return;
}
Future<Map<String, dynamic>> pushNativePage(dynamic params) async {
print(params);
Map<String, dynamic> result = {
"userInfo":{
"nickName" : "haley",
"avatarUrl" : "https://www.finclip.com",
"gender" : 1,
"country" : "China",
"province" : "Guangdong",
"city" : "shenzhen",
}
};
return Future.value(result);
}
Future<Map<String, dynamic>> getUserProfile(dynamic params) async {
Map<String, dynamic> result = {
"userInfo":{
@ -147,7 +126,7 @@ class _MyAppState extends State<MyApp> {
);
}
Widget _buildAppletWidget(String appletId, String appletName, int index, Map<String, String>? startParams) {
Widget _buildAppletWidget(String appletId, String appletName) {
return Container(
margin: EdgeInsets.only(left: 20, top: 30, right: 20),
child: Column(
@ -163,43 +142,31 @@ class _MyAppState extends State<MyApp> {
Container(
height: 100,
child: GridView.count(
crossAxisCount: 4,
crossAxisCount: 3,
childAspectRatio: 2,
crossAxisSpacing: 10,
crossAxisSpacing: 30,
// physics: NeverScrollableScrollPhysics(),
children: [
_buildAppletItem(appletId, "open", () {
_buildAppletItem(appletId, "打开小程序", () {
TranstionStyle style = TranstionStyle.TranstionStyleUp;
FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST;
if (index == 1) {
mode = FCReLaunchMode.ONLY_PARAMS_DIFF;
if (appletId == "5f72e3559a6a7900019b5baa") {
style = TranstionStyle.TranstionStylePush;
} else if (index == 2) {
mode = FCReLaunchMode.ALWAYS;
} else if (index == 3) {
mode = FCReLaunchMode.NEVER;
}
RemoteAppletRequest request = RemoteAppletRequest(
apiServer: 'https://api.finclip.com',
appletId: appletId,
transitionStyle: style,
reLaunchMode: mode,
startParams: startParams);
RemoteAppletRequest request = RemoteAppletRequest(apiServer: 'https://api.finclip.com', appletId: appletId, transitionStyle: style);
Mop.instance.startApplet(request);
// Mop.instance.qrcodeOpenApplet('https://api.finclip.com/api/v1/mop/runtime/applet/-f-MGYzN2Q1YTYzMmI2MWIyZg--');
}),
_buildAppletItem(appletId, "finish", () {
_buildAppletItem(appletId, "finishRunningApplet", () {
Mop.instance.finishRunningApplet(appletId, true);
}),
_buildAppletItem(appletId, "remove", () {
_buildAppletItem(appletId, "removeUsedApplet", () {
Mop.instance.removeUsedApplet(appletId);
}),
_buildAppletItem(appletId, "finishAll", () {
Mop.instance.clearApplets();
}),
// _buildAppletItem(appletId, "removeUsedApplet", () {
// Mop.instance.removeUsedApplet(appletId);
// }),
],
),
)
@ -215,29 +182,13 @@ class _MyAppState extends State<MyApp> {
home: Scaffold(
appBar: AppBar(
title: const Text('凡泰极客小程序 Flutter 插件'),
actions: <Widget>[
Builder(
builder: (context) {
return IconButton(
icon: Icon(Icons.more_horiz),
tooltip: 'More',
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => TestPage()),
);
},
);
},
),
],
),
body: Column(
children: <Widget>[
_buildAppletWidget("5facb3a52dcbff00017469bd", "画图小程序", 0, {'query':'ramdom='+context.hashCode.toString()}),
_buildAppletWidget("5f72e3559a6a7900019b5baa", "官方小程序", 1, {'query':'key=value'}),
_buildAppletWidget("5f17f457297b540001e06ebb", "api测试小程序", 2, null),
_buildAppletWidget("61386f6484dd160001d3e1ab", "测试小程序", 3, {'query':'ramdom='+context.hashCode.toString()}),
_buildAppletWidget("5facb3a52dcbff00017469bd", "画图小程序"),
_buildAppletWidget("5f72e3559a6a7900019b5baa", "官方小程序"),
_buildAppletWidget("5f17f457297b540001e06ebb", "api测试小程序"),
_buildAppletWidget("61386f6484dd160001d3e1ab", "测试小程序"),
],
),
@ -311,12 +262,6 @@ class MyAppletHandler extends AppletHandler {
return Future.value(result);
}
// @override
// Future<Map<String, dynamic>> getUserInfo() {
// // TODO: implement getUserInfo
// throw UnimplementedError();
// }
@override
Future<void> onCustomMenuClick(String appId, String path, String menuId, String appInfo) {
// TODO: implement onCustomMenuClick

View File

@ -1,136 +0,0 @@
import 'package:flutter/material.dart';
import 'package:mop/mop.dart';
class TestPage extends StatefulWidget {
@override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
final TextEditingController _controller1 = TextEditingController(text: '5f72e3559a6a7900019b5baa');
final TextEditingController _controller2 = TextEditingController();
final TextEditingController _controller3 = TextEditingController(text: 'key1=value2&name=zhangsan');
final TextEditingController _controller4 = TextEditingController(text: 'https://api.finclip.com/api/v1/mop/runtime/applet/-f-f1362bb056a265aa--');
int _selectedRadio = 0;
void _handleRadioValueChange(int? value) {
setState(() {
_selectedRadio = value!;
});
}
void _handleButtonPress() {
//
String appId = _controller1.text.trim();
String path = _controller2.text.trim();
String query = _controller3.text.trim();
int index = _selectedRadio;
FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST;
if (index == 1) {
mode = FCReLaunchMode.ONLY_PARAMS_DIFF;
} else if (index == 2) {
mode = FCReLaunchMode.ALWAYS;
} else if (index == 3) {
mode = FCReLaunchMode.NEVER;
}
Map<String, String>? startParams = {};
if (path.length > 0) {
startParams["path"] = path;
}
if (query.length > 0) {
startParams["query"] = query;
}
RemoteAppletRequest request = RemoteAppletRequest(
apiServer: 'https://api.finclip.com',
appletId: appId,
reLaunchMode: mode,
startParams: startParams);
Mop.instance.startApplet(request);
}
void _handleqrCodeButtonPress() {
String qrcode = _controller4.text.trim();
int index = _selectedRadio;
FCReLaunchMode mode = FCReLaunchMode.PARAMS_EXIST;
if (index == 1) {
mode = FCReLaunchMode.ONLY_PARAMS_DIFF;
} else if (index == 2) {
mode = FCReLaunchMode.ALWAYS;
} else if (index == 3) {
mode = FCReLaunchMode.NEVER;
}
QRCodeAppletRequest qrcodeRequest = QRCodeAppletRequest(qrcode, reLaunchMode: mode);
Mop.instance.qrcodeStartApplet(qrcodeRequest);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试页面'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
_buildTextField(_controller1, '小程序id'),
_buildTextField(_controller2, '输入path'),
_buildTextField(_controller3, '输入query'),
_buildTextField(_controller4, '二维码地址'),
SizedBox(height: 10),
Column(
children: <Widget>[
_buildRadioTile(0, 'ParamExist'),
_buildRadioTile(1, 'OnlyParamDiff'),
_buildRadioTile(2, 'Always'),
_buildRadioTile(3, 'Never'),
],
),
SizedBox(height: 10),
ElevatedButton(
onPressed: _handleButtonPress,
child: Text('打开小程序'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: _handleqrCodeButtonPress,
child: Text('二维码打开小程序'),
),
],
),
),
);
}
Widget _buildTextField(TextEditingController controller, String hintText) {
return TextField(
controller: controller,
decoration: InputDecoration(
hintText: hintText,
border: OutlineInputBorder(),
contentPadding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
),
);
}
Widget _buildRadioTile(int value, String title) {
return GestureDetector(
onTap: () => _handleRadioValueChange(value),
child: Row(
children: <Widget>[
Radio(
value: value,
groupValue: _selectedRadio,
onChanged: _handleRadioValueChange,
),
Text(title),
],
),
);
}
}

View File

@ -7,7 +7,7 @@ packages:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.8.2"
version: "2.9.0"
boolean_selector:
dependency: transitive
description:
@ -21,21 +21,14 @@ packages:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.1"
version: "1.2.1"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.1.1"
collection:
dependency: transitive
description:
@ -56,7 +49,7 @@ packages:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
@ -75,7 +68,7 @@ packages:
name: flutter_plugin_android_lifecycle
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.14"
version: "2.0.9"
flutter_test:
dependency: "direct dev"
description: flutter
@ -94,35 +87,35 @@ packages:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.11"
version: "0.12.12"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.4"
version: "0.1.5"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.7.0"
version: "1.8.0"
mop:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "2.45.1"
version: "2.41.1"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.1"
version: "1.8.2"
sky_engine:
dependency: transitive
description: flutter
@ -134,7 +127,7 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.8.2"
version: "1.9.0"
stack_trace:
dependency: transitive
description:
@ -155,21 +148,21 @@ packages:
name: string_scanner
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.1.1"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.9"
version: "0.4.12"
vector_math:
dependency: transitive
description:
@ -178,5 +171,5 @@ packages:
source: hosted
version: "2.1.2"
sdks:
dart: ">=2.17.0 <3.0.0"
dart: ">=2.17.0-0 <3.0.0"
flutter: ">=3.0.0"

View File

@ -37,32 +37,43 @@
if([result isKindOfClass:[FlutterError class]]|| [result isKindOfClass:[FlutterMethodNotImplemented class] ])
{
completion(FATExtensionCodeFailure,nil);
} else {
}else
{
completion(FATExtensionCodeSuccess,result);
}
}];
}
- (NSDictionary *)getUserInfoWithAppletInfo:(FATAppletInfo *)appletInfo {
NSLog(@"getUserInfoWithAppletInfo");
__block NSDictionary *userInfo;
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
[channel invokeMethod:@"extensionApi:getUserInfo" arguments:nil result:^(id _Nullable result) {
CFRunLoopStop(CFRunLoopGetMain());
userInfo = result;
}];
CFRunLoopRun();
return userInfo;
}
- (BOOL)appletInfo:(FATAppletInfo *)appletInfo didClickMoreBtnAtPath:(NSString *)path {
NSLog(@"appletInfo:didClickMoreBtnAtPath");
__block BOOL flag = NO;
__block BOOL flag;
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
[channel invokeMethod:@"extensionApi:customCapsuleMoreButtonClick" arguments:@{@"appId": appletInfo.appId} result:^(id _Nullable result) {
CFRunLoopStop(CFRunLoopGetMain());
if ([result isKindOfClass:[NSNumber class]]) {
flag = [result boolValue];
}
CFRunLoopStop(CFRunLoopGetMain());
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CFRunLoopStop(CFRunLoopGetMain());
});
CFRunLoopRun();
return flag;
}
- (NSArray<id<FATAppletMenuProtocol>> *)customMenusInApplet:(FATAppletInfo *)appletInfo atPath:(NSString *)path {
NSLog(@"customMenusInApplet");
__block NSArray *list = @[];
__block NSArray *list;
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
[channel invokeMethod:@"extensionApi:getCustomMenus" arguments:@{@"appId": appletInfo.appId} result:^(id _Nullable result) {
CFRunLoopStop(CFRunLoopGetMain());
@ -70,9 +81,6 @@
list = result;
}
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CFRunLoopStop(CFRunLoopGetMain());
});
CFRunLoopRun();
NSMutableArray *models = [NSMutableArray array];
@ -109,7 +117,6 @@
NSMutableDictionary *shareDic = [[NSMutableDictionary alloc] initWithDictionary:[self dictionaryRepresentation:appletInfo]];
[shareDic setValue:@{@"desc" : shareDic[@"originalInfo"][@"customData"][@"detailDescription"]} forKey:@"params"];
[shareDic setValue:contentInfo[@"query"] forKey:@"query"];
[shareDic removeObjectForKey:@"libraryInfo"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:shareDic options:NSJSONWritingPrettyPrinted error:&parseError];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSDictionary *arguments = @{

View File

@ -23,22 +23,6 @@
return _instance;
}
- (BOOL)getUserInfoWithAppletInfo:(FATAppletInfo *)appletInfo bindGetUserInfo:(void (^)(NSDictionary *result))bindGetUserInfo
{
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
NSLog(@"getUserInfoWithAppletInfo:%@", channel);
[channel invokeMethod:@"extensionApi:getUserInfo" arguments:nil result:^(id _Nullable result) {
NSDictionary *userInfo;
if (![result isKindOfClass:[NSDictionary class]]) {
userInfo = @{@"errMsg":@"getUserInfo:fail return value format invalid"};
} else {
userInfo = result;
}
bindGetUserInfo(userInfo);
}];
return YES;
}
- (BOOL)getUserProfileWithAppletInfo:(FATAppletInfo *)appletInfo
bindGetUserProfile:(void (^)(NSDictionary *result))bindGetUserProfile
{

View File

@ -13,10 +13,9 @@
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
NSLog(@"clearApplets");
[[FATClient sharedClient] closeAllAppletsWithCompletion:^{
[[FATClient sharedClient] clearMemoryCache];
success(@{});
}];
[[FATClient sharedClient]clearMemoryCache];
[[FATClient sharedClient]clearLocalApplets];
success(@{});
}
@end

View File

@ -13,7 +13,7 @@
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
NSLog(@"closeAllApplets");
[[FATClient sharedClient] closeAllAppletsWithCompletion:nil];
[[FATClient sharedClient] closeAllApplets];
success(@{});
}

View File

@ -7,7 +7,6 @@
#import "Mop_initSDK.h"
#import "MOPTools.h"
#import "FinAppletExt.h"
@implementation MOP_initSDK
@ -36,9 +35,6 @@
storeConfig.encryptServerData = [dict[@"encryptServerData"] boolValue];
storeConfig.enablePreloadFramework = [storeConfig.apiServer isEqualToString:@"https://api.finclip.com"];
[storeArrayM addObject:storeConfig];
//google map key
[[FATExtClient sharedClient] registerGoogleMapService:dict[@"googleMapApiKey"] placesKey:dict[@"googleMapApiKey"]];
}
config = [FATConfig configWithStoreConfigs:storeArrayM];
} else {
@ -47,8 +43,6 @@
}
config.currentUserId = self.config[@"userId"];
config.channel = self.config[@"channel"];
config.phone = self.config[@"phone"];
config.productIdentification = self.config[@"productIdentification"];
config.disableAuthorize = [self.config[@"disableRequestPermissions"] boolValue];
config.appletAutoAuthorize = [self.config[@"appletAutoAuthorize"] boolValue];
@ -69,18 +63,14 @@
config.h5AjaxHookRequestKey = self.config[@"h5AjaxHookRequestKey"];
config.pageCountLimit = [self.config[@"pageCountLimit"] integerValue];
config.schemes = self.config[@"schemes"];
config.webViewInspectable = [self.config[@"debug"] boolValue];
NSInteger languageInteger = [self.config[@"language"] integerValue];
if (self.config[@"backgroundFetchPeriod"]) {
config.backgroundFetchPeriod = [self.config[@"backgroundFetchPeriod"] integerValue];
}
if (languageInteger == 1) {
config.language = FATPreferredLanguageEnglish;
} else {
config.language = FATPreferredLanguageSimplifiedChinese;
}
config.customLanguagePath = self.config[@"customLanguagePath"];
NSError* error = nil;
FATUIConfig *uiconfig = [[FATUIConfig alloc]init];
if (_uiConfig) {
@ -114,7 +104,6 @@
uiconfig.hideRefreshMenu = [_uiConfig[@"isHideRefreshMenu"] boolValue];
uiconfig.hideFavoriteMenu = [_uiConfig[@"isHideFavoriteMenu"] boolValue];
uiconfig.hideAddToDesktopMenu = [_uiConfig[@"isHideAddToDesktopMenu"] boolValue];
uiconfig.hideClearCacheMenu = [_uiConfig[@"isHideClearCacheMenu"] boolValue];
//
if (_uiConfig[@"capsuleConfig"]) {
@ -267,21 +256,17 @@
return;
}
int logMaxAliveSec = [self.config[@"logMaxAliveSec"] intValue];
if (logMaxAliveSec) {
[[FATClient sharedClient].logManager setLogFileAliveDuration:logMaxAliveSec];
}
BOOL debug = [self.config[@"debug"] boolValue];
NSInteger logLevelIntValue = [self.config[@"logLevel"] integerValue];
if (debug && logLevelIntValue < 5) {
if (logLevelIntValue >= 5) {
[[FATClient sharedClient].logManager closeLog];
} else {
FATLogLevel logLevel = logLevelIntValue;
NSString *logDir = self.config[@"logDir"];
[[FATClient sharedClient].logManager initLogWithLogDir:logDir logLevel:logLevel consoleLog:YES];
} else {
[FATClient sharedClient].enableLog = NO;
}
[[FATClient sharedClient] setEnableLog:YES];
success(@{});
}

View File

@ -7,8 +7,7 @@
#import "MOP_initialize.h"
#import <FinApplet/FinApplet.h>
#import "FinAppletExt.h"
#import <FinAppletBLE/FinAppletBLE.h>
#import <FinAppletExt/FinAppletExt.h>
#import "MOPTools.h"
@implementation MOP_initialize
@ -127,6 +126,9 @@
// [[FATExtClient sharedClient] fat_prepareExtensionApis];
[[FATClient sharedClient].logManager initLogWithLogDir:nil logLevel:FATLogLevelVerbose consoleLog:YES];
[[FATClient sharedClient] setEnableLog:YES];
success(@{});

View File

@ -12,7 +12,6 @@ NS_ASSUME_NONNULL_BEGIN
@interface MOP_qrcodeOpenApplet : MOPBaseApi
@property (nonatomic,copy) NSString *qrcode;
@property (nonatomic,copy) NSString *reLaunchMode;
@end

View File

@ -15,7 +15,6 @@
NSLog(@"MOP_qrcodeOpenApplet:%@", self.qrcode);
FATAppletQrCodeRequest *qrcodeRequest = [[FATAppletQrCodeRequest alloc] init];
qrcodeRequest.qrCode = self.qrcode;
qrcodeRequest.reLaunchMode = [self.reLaunchMode intValue];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UIViewController *currentVC = [MOPTools topViewController];

View File

@ -15,13 +15,15 @@
{
NSLog(@"MOP_registerExtensionApi");
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
NSString *name = self.name;
[[FATClient sharedClient] registerExtensionApi:name handler:^(FATAppletInfo *appletInfo, id param, FATExtensionApiCallback callback) {
NSLog(@"channel:%@---invoke ExtensionApi:%@, param:%@", channel, name, param);
NSString *api = [@"extensionApi:" stringByAppendingString:name];
[[FATClient sharedClient] registerExtensionApi:self.name handle:^(id param, FATExtensionApiCallback callback) {
NSLog(@"invoke ExtensionApi:");
NSLog(@"%@",self.name);
NSLog(@"%@",param);
NSString* api = [@"extensionApi:" stringByAppendingString:self.name];
[channel invokeMethod:api arguments:param result:^(id _Nullable result) {
NSLog(@"extensionApi [%@] reslut:%@", name, result);
NSLog(@"extensionApi reslut:%@",result);
// flutter
// BOOL isFlutterError = [result isKindOfClass:[FlutterError class]] || result == FlutterMethodNotImplemented;
BOOL isValid = [result isKindOfClass:[NSDictionary class]];
if (!isValid) {
NSLog(@"extensionApi reslut is not NSDictionary");
@ -32,7 +34,7 @@
BOOL hasError = [[result allKeys] containsObject:@"errMsg"];
if (hasError) {
NSString *errMsg = result[@"errMsg"];
NSString *errPrefix = [NSString stringWithFormat:@"%@:fail", name];
NSString *errPrefix = [NSString stringWithFormat:@"%@:fail", self.name];
BOOL isFail = [errMsg hasPrefix:errPrefix];
if (isFail) {
NSLog(@"extensionApi reslut:fail");

View File

@ -1,18 +0,0 @@
//
// MOP_registerSyncExtensionApi.h
// mop
//
// Created by Stewen on 2023/6/30.
//
#import "MOPBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface MOP_registerSyncExtensionApi : MOPBaseApi
@property(nonatomic, copy) NSString* name;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,35 +0,0 @@
//
// MOP_registerSyncExtensionApi.m
// mop
//
// Created by Stewen on 2023/6/30.
//
#import "MOP_registerSyncExtensionApi.h"
#import "MopPlugin.h"
#import <FinApplet/FinApplet.h>
#import "PhizLanguageData.h"
@implementation MOP_registerSyncExtensionApi
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *,id> * _Nonnull))success failure:(void (^)(id _Nullable))failure cancel:(void (^)(void))cancel
{
// NSLog(@"MOP_registerSyncExtensionApi,name=%@",self.name);
FlutterMethodChannel *channel = [[MopPlugin instance] methodChannel];
[[FATClient sharedClient] registerSyncExtensionApi:self.name handler:^NSDictionary *(FATAppletInfo *appletInfo, id param) {
// NSLog(@"MOP_registerSyncExtensionApi handler,name=%@ %@",self.name,[PhizLanguageData sharedInstance].languageCode);
if([self.name isEqualToString:@"getLanguageCodeSync"]){
NSDictionary *resultDict = [NSDictionary dictionary];
NSString* shortCode = [PhizLanguageData sharedInstance].languageCode;
NSString* countryCode = [PhizLanguageData sharedInstance].countryCode;
resultDict = @{@"languageCode":shortCode,@"countryCode":countryCode};
return resultDict;
}
return @{};
}];
success(@{});
}
@end

View File

@ -17,9 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSDictionary *startParams;
@property (nonatomic, copy) NSString *offlineMiniprogramZipPath;
@property (nonatomic, copy) NSString *offlineFrameworkZipPath;
@property (nonatomic, copy) NSString *animated;
@property (nonatomic, copy) NSString *transitionStyle;
@property (nonatomic, copy) NSString *reLaunchMode;
@property (nonatomic, strong) NSString *animated;
@property (nonatomic, strong) NSString *transitionStyle;
@end

View File

@ -26,7 +26,6 @@
request.offlineFrameworkZipPath = self.offlineFrameworkZipPath;
request.animated = [self.animated boolValue];
request.transitionStyle = [self.transitionStyle intValue];
request.reLaunchMode = [self.reLaunchMode intValue];
//
[[FATClient sharedClient] startAppletWithRequest:request InParentViewController:currentVC completion:^(BOOL result, NSError *error) {

View File

@ -1,20 +0,0 @@
//
// PhizLanguageData.h
// FinDemo
//
// Created by stewen on 2023/8/4.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface PhizLanguageData : NSObject
@property (nonatomic, copy) NSString *languageCode;
@property (nonatomic, copy) NSString *countryCode;
+ (instancetype)sharedInstance;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,23 +0,0 @@
//
// PhizLanguageData.m
// FinDemo
//
// Created by stewen on 2023/8/4.
//
#import "PhizLanguageData.h"
@implementation PhizLanguageData
+ (instancetype)sharedInstance {
static PhizLanguageData *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[PhizLanguageData alloc] init];
sharedInstance.languageCode = @"en"; // Set default language code
sharedInstance.countryCode = @"US";
});
return sharedInstance;
}
@end

View File

@ -1,46 +0,0 @@
//
// FATClient+ext.h
// Pods
//
// Created by on 2021/11/15.
//
#ifndef FATClient_ext_h
#define FATClient_ext_h
#import <FinApplet/FinApplet.h>
@interface FATClient (FATAppletExt)
///
/// @param authType 0: 1: 2: 3:
/// @param appletId id
/// @param complete status: 0 1: 2: sdk
- (void)fat_requestAppletAuthorize:(FATAuthorizationType)authType appletId:(NSString *)appletId complete:(void (^)(NSInteger status))complete;
/// sdkAPIsdksdk APIapi
/// @param extApiName API
/// @param handler
- (BOOL)registerInnerExtensionApi:(NSString *)extApiName handler:(void (^)(FATAppletInfo *appletInfo, id param, FATExtensionApiCallback callback))handler;
/**
sdkAPIsdksdk APIapi
@param syncExtApiName api
@param handler
@return
*/
- (BOOL)registerInnerSyncExtensionApi:(NSString *)syncExtApiName handler:(NSDictionary *(^)(FATAppletInfo *appletInfo, id param))handler;
/**
HTML apisdkapi
@param webApiName api
@param handler
*/
- (BOOL)fat_registerInnerWebApi:(NSString *)webApiName handler:(void (^)(FATAppletInfo *appletInfo, id param, FATExtensionApiCallback callback))handler;
@end
#endif /* FATClient_ext_h */

View File

@ -1,28 +0,0 @@
//
// FATExtClient.h
// FinAppletExtension
//
// Created by Haley on 2020/8/11.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FATExtClient : NSObject
+ (instancetype)sharedClient;
///
+ (NSString *)SDKVersion;
- (void)fat_prepareExtensionApis;
- (void)registerGoogleMapService:(NSString*)apiKey placesKey:(NSString*)placeKey;
/// webView
/// @param frame frame
/// @param URL URL
/// @param appletId ID
- (UIView *)webViewWithFrame:(CGRect)frame URL:(NSURL *)URL appletId:(NSString *)appletId;
@end

View File

@ -1,92 +0,0 @@
//
// FATExtClient.m
// FinAppletExtension
//
// Created by Haley on 2020/8/11.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtClient.h"
#import "FATExtBaseApi.h"
#import "FATWebView.h"
#import <FinApplet/FinApplet.h>
#import "FATExtPrivateConstant.h"
#import "FATExtMapManager.h"
#import "FATMapViewDelegate.h"
#import "FATClient+ext.h"
static FATExtClient *instance = nil;
@implementation FATExtClient
+ (instancetype)sharedClient {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[FATExtClient alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
+ (NSString *)SDKVersion
{
return FATExtVersionString;
}
///
/// @param mapClass UIViewFATMapViewDelegate
- (BOOL)fat_registerMapClass:(Class)mapClass {
if (![mapClass isSubclassOfClass:UIView.class]) {
return NO;
}
if (![mapClass conformsToProtocol:@protocol(FATMapViewDelegate)]) {
return NO;
}
[FATExtMapManager shareInstance].mapClass = mapClass;
return YES;
}
- (void)registerGoogleMapService:(NSString*)apiKey placesKey:(NSString*)placeKey{
//[GMSServices provideAPIKey: apiKey];
[FATExtMapManager shareInstance].googleMapApiKey = apiKey;
if(placeKey == nil || [placeKey length] == 0){
[FATExtMapManager shareInstance].placesApiKey = apiKey;
}else{
[FATExtMapManager shareInstance].placesApiKey = placeKey;
}
}
- (void)fat_prepareExtensionApis {
}
- (void)registerExtensionBLEApi {
//SDK
}
- (UIView *)webViewWithFrame:(CGRect)frame URL:(NSURL *)URL appletId:(NSString *)appletId {
if (![FATClient sharedClient].inited) {
NSLog(@"appKey invalid");
return nil;
}
if (!URL || ![URL isKindOfClass:[NSURL class]]) {
NSLog(@"URL invalid");
return nil;
}
FATWebView *webView = [[FATWebView alloc] initWithFrame:frame URL:URL appletId:appletId];
return webView;
}
@end

View File

@ -1,34 +0,0 @@
//
// UIView+FATExtFrame.h
// FinAppletBDMap
//
// Created by 耀 on 2021/12/12.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (FATExtFrame)
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGPoint origin;
@property (nonatomic, assign) CGFloat top;
@property (nonatomic, assign) CGFloat bottom;
@property (nonatomic, assign) CGFloat left;
@property (nonatomic, assign) CGFloat right;
//selfView
- (BOOL)intersectWithView:(UIView *)view;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,131 +0,0 @@
//
// UIView+FATExtFrame.m
// FinAppletBDMap
//
// Created by 耀 on 2021/12/12.
//
#import "UIView+FATExtFrame.h"
@implementation UIView (FATExtFrame)
- (void)setX:(CGFloat)x {
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (CGFloat)x {
return self.frame.origin.x;
}
- (void)setY:(CGFloat)y {
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)y {
return self.frame.origin.y;
}
- (void)setCenterX:(CGFloat)centerX {
CGPoint center = self.center;
center.x = centerX;
self.center = center;
}
- (CGFloat)centerX {
return self.center.x;
}
- (void)setCenterY:(CGFloat)centerY {
CGPoint center = self.center;
center.y = centerY;
self.center = center;
}
- (CGFloat)centerY {
return self.center.y;
}
- (void)setWidth:(CGFloat)width {
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (CGFloat)width {
return self.frame.size.width;
}
- (void)setHeight:(CGFloat)height {
CGRect frame = self.frame;
frame.size.height = height;
self.frame = frame;
}
- (CGFloat)height {
return self.frame.size.height;
}
- (void)setSize:(CGSize)size {
CGRect frame = self.frame;
frame.size = size;
self.frame = frame;
}
- (CGSize)size {
return self.frame.size;
}
- (CGPoint)origin {
return self.frame.origin;
}
- (void)setOrigin:(CGPoint)origin {
CGRect frame = self.frame;
frame.origin = origin;
self.frame = frame;
}
- (void)setTop:(CGFloat)t {
self.frame = CGRectMake(self.left, t, self.width, self.height);
}
- (CGFloat)top {
return self.frame.origin.y;
}
- (void)setBottom:(CGFloat)b {
self.frame = CGRectMake(self.left, b - self.height, self.width, self.height);
}
- (CGFloat)bottom {
return self.frame.origin.y + self.frame.size.height;
}
- (void)setLeft:(CGFloat)l {
self.frame = CGRectMake(l, self.top, self.width, self.height);
}
- (CGFloat)left {
return self.frame.origin.x;
}
- (void)setRight:(CGFloat)r {
self.frame = CGRectMake(r - self.width, self.top, self.width, self.height);
}
- (CGFloat)right {
return self.frame.origin.x + self.frame.size.width;
}
//selfView nilwindow
- (BOOL)intersectWithView:(UIView *)view {
if (view == nil) view = [UIApplication sharedApplication].keyWindow;
CGRect rect1 = [self convertRect:self.bounds toView:nil];
CGRect rect2 = [view convertRect:view.bounds toView:nil];
return CGRectIntersectsRect(rect1, rect2);
}
@end

View File

@ -1,21 +0,0 @@
//
// FATExtConstant.h
// FinAppletExt
//
// Created by Haley on 2021/9/6.
//
#ifndef FATExtPrivateConstant_h
#define FATExtPrivateConstant_h
static NSString *kExtSendToCoreEventNotification = @"kExtSendToCoreEventNotification";
static NSString *FATExtVersionString = @"2.41.3";
typedef NS_ENUM(NSUInteger, FATExtEventType) {
FATExtEventTypeService, // service
FATExtEventTypePage, // page
FATExtEventTypeView, // view
};
#endif /* FATExtPrivateConstant_h */

View File

@ -1,36 +0,0 @@
//
// FATExtAVManager.h
// FinAppletExt
//
// Created by Haley on 2020/8/14.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^FATExtAVSuccess)(NSString *filePath);
typedef void (^FATExtAVFail)(NSString *failMsg);
@interface FATExtAVManager : NSObject
+ (instancetype)sharedManager;
/**
@param success
@param fail
*/
- (void)startRecordWithSuccess:(FATExtAVSuccess)success fail:(FATExtAVFail)fail;
/**
*/
- (void)stopRecord;
/**
*/
- (void)checkRecordState;
@end

View File

@ -1,195 +0,0 @@
//
// FATExtAVManager.m
// FinAppletExt
//
// Created by Haley on 2020/8/14.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtAVManager.h"
#import "FATExtFileManager.h"
#import <AVFoundation/AVFoundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <FinApplet/FinApplet.h>
@interface FATExtAVManager () <AVAudioRecorderDelegate>
@property (nonatomic, strong) AVAudioRecorder *recorder;
@property (nonatomic, copy) FATExtAVSuccess recordSuccess;
@property (nonatomic, copy) FATExtAVFail recordFail;
@end
@implementation FATExtAVManager
+ (instancetype)sharedManager {
static id _sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedInstance = [[FATExtAVManager alloc] init];
[_sharedInstance add_notifications];
});
return _sharedInstance;
}
- (void)add_notifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appletPageDisappear:) name:kFATPageDidDisappearNotification object:nil];
}
- (void)appletPageDisappear:(NSNotification *)notification
{
if (self.recorder) {
[self.recorder pause];
if (self.recordFail) {
self.recordFail(@"fail");
}
[self.recorder deleteRecording];
self.recorder = nil;
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
}
/**
@param success
@param fail
*/
- (void)startRecordWithSuccess:(FATExtAVSuccess)success fail:(FATExtAVFail)fail {
if ([self.recorder isRecording]) {
fail(@"正在录音中...");
return;
}
self.recordSuccess = success;
self.recordFail = fail;
self.recorder = [self createAudioRecord];
[self.recorder prepareToRecord];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL];
[audioSession setActive:YES error:NULL];
[self.recorder recordForDuration:60];
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
}
/**
*/
- (void)stopRecord {
if (self.recorder) {
[self.recorder stop];
self.recorder = nil;
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
}
- (void)checkRecordState {
if ([self.recorder isRecording]) {
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
}
}
#pragma mark - private method
- (AVAudioRecorder *)createAudioRecord {
// 使 1200KB
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kAudioFormatMPEG4AAC], AVFormatIDKey,
[NSNumber numberWithFloat:16000.0], AVSampleRateKey,
[NSNumber numberWithInt:1], AVNumberOfChannelsKey,
nil];
// 使md5
NSString *currentDt = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]];
NSData *data = [currentDt dataUsingEncoding:NSUTF8StringEncoding];
NSString *nameMD5 = [self fat_md5WithBytes:(char *)[data bytes] length:data.length];
NSString *fileName = [NSString stringWithFormat:@"tmp_%@.m4a", nameMD5];
NSString *filePath = [[self tmpDir] stringByAppendingPathComponent:fileName];
AVAudioRecorder *recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:filePath] settings:settings error:nil];
recorder.delegate = self;
return recorder;
}
- (NSString *)tmpDir {
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
NSString *cacheDir = [FATExtFileManager appTempDirPath:appInfo.appId];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL flag = YES;
if (![fileManager fileExistsAtPath:cacheDir isDirectory:&flag]) {
[fileManager createDirectoryAtPath:cacheDir withIntermediateDirectories:YES attributes:nil error:nil];
}
return cacheDir;
}
- (NSString *)fat_md5WithBytes:(char *)bytes length:(NSUInteger)length {
unsigned char result[16];
CC_MD5(bytes, (CC_LONG)length, result);
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]];
}
#pragma mark - AVAudioRecord Delegate
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag {
NSString *filePath = recorder.url.lastPathComponent;
if (flag) {
if (self.recordSuccess) {
self.recordSuccess([@"finfile://" stringByAppendingString:filePath]);
}
} else {
[recorder deleteRecording];
if (self.recordFail) {
self.recordFail(@"fail");
}
}
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL];
[audioSession setActive:YES error:NULL];
self.recorder = nil;
self.recordSuccess = nil;
self.recordFail = nil;
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
@end

View File

@ -1,30 +0,0 @@
//
// FATExtFileManager.h
// FinAppletExt
//
// Created by Haley on 2020/8/17.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface FATExtFileManager : NSObject
/**
@return
*/
+ (NSString *)projectRootAppsDirPath;
/**
*/
+ (NSString *)appRootDirPath:(NSString *)appId;
/**
*/
+ (NSString *)appTempDirPath:(NSString *)appId;
@end

View File

@ -1,60 +0,0 @@
//
// FATExtFileManager.m
// FinAppletExt
//
// Created by Haley on 2020/8/17.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtFileManager.h"
#import "FATExtUtil.h"
#import <FinApplet/FinApplet.h>
static NSString *FATEXT_PROJECT_ROOT = @"FinChatRoot";
static NSString *FATEXT_PROJECT_ROOT_App = @"app";
static NSString *FATEXT_PROJECT_ROOT_Framework = @"framework";
@implementation FATExtFileManager
+ (NSString *)projectRootDirPath {
NSString *rootPath;
if ([FATExtUtil currentProductIdentificationIsEmpty]) {
rootPath = [NSTemporaryDirectory() stringByAppendingPathComponent:FATEXT_PROJECT_ROOT];
} else {
rootPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[FATExtUtil currentProductIdentification]];
}
return rootPath;
}
+ (NSString *)projectRootAppsDirPath {
NSString *rootPath = [[FATExtFileManager projectRootDirPath] stringByAppendingFormat:@"/%@", FATEXT_PROJECT_ROOT_App];
return rootPath;
}
/**
@return
*/
+ (NSString *)appRootDirPath:(NSString *)appId {
NSString *rootPath = [FATExtFileManager projectRootAppsDirPath];
NSString *appDirPath = [rootPath stringByAppendingPathComponent:appId];
return appDirPath;
}
/**
@return NSString *
*/
+ (NSString *)appTempDirPath:(NSString *)appId {
NSString *currtUserId = [FATExtUtil currentUserId];
NSString *tempFileCachePath = [[FATExtFileManager appRootDirPath:appId] stringByAppendingPathComponent:[currtUserId fat_md5String]];
tempFileCachePath = [tempFileCachePath stringByAppendingPathComponent:@"Temp"];
return tempFileCachePath;
}
@end

View File

@ -1,17 +0,0 @@
//
// FATExtLocationManager.h
// FinAppletExt
//
// Created by beetle_92 on 2022/8/19.
// Copyright © 2022 finogeeks. All rights reserved.
//
#import <CoreLocation/CoreLocation.h>
NS_ASSUME_NONNULL_BEGIN
@interface FATExtLocationManager : CLLocationManager
@end
NS_ASSUME_NONNULL_END

View File

@ -1,47 +0,0 @@
//
// FATExtLocationManager.m
// FinAppletExt
//
// Created by beetle_92 on 2022/8/19.
// Copyright © 2022 finogeeks. All rights reserved.
//
#import "FATExtLocationManager.h"
#import "FATExtAVManager.h"
#import "FATExtRecordManager.h"
#import "FATExt_LocationUpdateManager.h"
#import <FinApplet/FinApplet.h>
@implementation FATExtLocationManager
- (void)startUpdatingLocation {
[super startUpdatingLocation];
if ([self.delegate isKindOfClass:NSClassFromString(@"FATMapView")]) {
return;
}
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateLocation animate:YES];
}
}
- (void)stopUpdatingLocation {
[super stopUpdatingLocation];
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateLocation animate:NO];
[[FATExtAVManager sharedManager] checkRecordState];
[[FATExtRecordManager shareManager] checkRecordState];
[[FATExt_LocationUpdateManager sharedManager] checkLocationState];
});
}
}
@end

View File

@ -1,25 +0,0 @@
//
// FATExtMapManager.h
// FinAppletExt
//
// Created by 耀 on 2021/11/18.
//
#import <Foundation/Foundation.h>
#import "FATExtPrivateConstant.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExtMapManager : NSObject
@property (nonatomic, copy) NSString *pageId;
@property (nonatomic, strong) Class mapClass;
@property (nonatomic, strong) NSString *googleMapApiKey;
@property (nonatomic, strong) NSString *placesApiKey;
+ (instancetype)shareInstance;
@property (nonatomic, strong) NSMutableDictionary *dataDic;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,44 +0,0 @@
//
// FATExtMapManager.m
// FinAppletExt
//
// Created by 耀 on 2021/11/18.
//
#import "FATExtMapManager.h"
#import <FinApplet/FinApplet.h>
#import "FATMapViewDelegate.h"
#import "FATMapView.h"
static FATExtMapManager *instance = nil;
@implementation FATExtMapManager
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[FATExtMapManager alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
_dataDic = [[NSMutableDictionary alloc] init];
self.mapClass = FATMapView.class;
}
return self;
}
@end

View File

@ -1,30 +0,0 @@
//
// FATRecordManager.h
// FinAppletExt
//
// Created by Haley on 2021/1/21.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface FATExtRecordManager : NSObject
+ (instancetype)shareManager;
#pragma mark - new api
- (BOOL)startRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId eventBlock:(void (^)(NSInteger eventType,NSString *eventName, NSDictionary *paramDic,NSDictionary *extDic))eventBlock;
- (BOOL)pauseRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId;
- (BOOL)resumeRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId;
- (BOOL)stopRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId;
- (BOOL)checkRecordWithMethod:(NSString *)method data:(NSDictionary *)data appletId:(NSString *)appletId;
- (void)sendRecordFrameBufferWithData:(NSDictionary *)data appletId:(NSString *)appletId;
- (void)checkRecordState;
@end

View File

@ -1,362 +0,0 @@
//
// FATRecordManager.m
// FinAppletExt
//
// Created by Haley on 2021/1/21.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import "FATExtRecordManager.h"
#import "FATExtRecorder.h"
#import "FATExtUtil.h"
#import <FinApplet/FinApplet.h>
static FATExtRecordManager *instance = nil;
@interface FATExtRecordManager () <FATExtRecorderDelegate>
@property (nonatomic, strong) NSMutableDictionary *recordDictionary;
@property (nonatomic, strong) NSMutableDictionary *recorderDict;
@end
@implementation FATExtRecordManager
+ (instancetype)shareManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[FATExtRecordManager alloc] init];
instance.recordDictionary = [[NSMutableDictionary alloc] init];
instance.recorderDict = [[NSMutableDictionary alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
[self p_addNotifications];
}
return self;
}
#pragma mark - private methods
- (void)p_addNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)_clearAudioSession {
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL];
[audioSession setActive:YES error:NULL];
}
#pragma mark - notification handler
- (void)applicationDidEnterBackground:(NSNotification *)notice {
[self.recorderDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, FATExtRecorder *recorder, BOOL * _Nonnull stop) {
if (!recorder.isPausing) {
[self pauseRecordWithData:nil appletId:key];
}
}];
}
#pragma mark - new api
- (BOOL)startRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId eventBlock:(void (^)(NSInteger eventType,NSString *eventName, NSDictionary *paramDic,NSDictionary *extDic))eventBlock {
FATExtRecorder *record = [[FATExtRecorder alloc] init];
record.delegate = self;
record.eventCallBack = eventBlock;
BOOL started = [record startRecordWithDict:data appId:appletId];
if (started) {
[self.recorderDict setObject:record forKey:appletId];
NSDictionary *params = @{@"method" : @"onStart"};
if (eventBlock) {
eventBlock(0,@"onRecorderManager",params,nil);
}
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
return YES;
}
return NO;
}
- (BOOL)pauseRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId {
FATExtRecorder *record = [self.recorderDict objectForKey:appletId];
if (!record) {
return NO;
}
BOOL result = [record pauseRecord];
if (result) {
if (record.eventCallBack) {
NSDictionary *params = @{@"method" : @"onPause"};
record.eventCallBack(0, @"onRecorderManager", params,nil);
}
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
return YES;
}
return NO;
}
- (BOOL)resumeRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId {
FATExtRecorder *record = [self.recorderDict objectForKey:appletId];
BOOL result = [record resumeRecord];
if (result) {
if (record.eventCallBack) {
NSDictionary *params = @{@"method" : @"onResume"};
record.eventCallBack(0, @"onRecorderManager", params,nil);
}
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
return YES;
}
return NO;
}
- (BOOL)stopRecordWithData:(NSDictionary *)data appletId:(NSString *)appletId {
FATExtRecorder *record = [self.recorderDict objectForKey:appletId];
[record stopRecord];
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
return YES;
}
- (BOOL)checkRecordWithMethod:(NSString *)method data:(NSDictionary *)data appletId:(NSString *)appletId {
FATExtRecorder *recorder = [self.recorderDict objectForKey:appletId];
if ([method isEqualToString:@"start"]) { //
if (recorder.isRecording || recorder.isPausing) {
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : @"is recording or paused"},
};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
return NO;
}
} else if ([method isEqualToString:@"pause"]) { //
if (![recorder isRecording]) {
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : @"not recording"},
};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
return NO;
}
} else if ([method isEqualToString:@"resume"]) { //
if (!recorder.isPausing) {
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : @"not paused"},
};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
return NO;
}
} else if ([method isEqualToString:@"stop"]) { //
if (!recorder.isStarted) {
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : @"recorder not start"},
};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
return NO;
}
}
return YES;
}
- (void)sendRecordFrameBufferWithData:(NSDictionary *)data appletId:(NSString *)appletId {
FATExtRecorder *recorder = [self.recorderDict objectForKey:appletId];
recorder.frameState = FATFrameStatePrepareToSend;
if (recorder.frameInfoArray.count == 0) {
recorder.waitToSendBuffer = YES;
return;
}
[self sendFrameDataWithRecorder:recorder withFrameBufferData:nil];
}
- (void)sendFrameDataWithRecorder:(FATExtRecorder *)recorder withFrameBufferData:(NSData *)data {
// 0.
recorder.waitToSendBuffer = NO;
recorder.frameState = FATFrameStateAlreadyWillSend;
// 1.bufferjscore
NSDictionary *dict = [recorder.frameInfoArray firstObject];
if (!dict) {
return;
}
// NSNumber *frameIndex = dict[@"frameIndex"];
NSString *frameBufferKey = dict[@"frameBufferKey"];
NSString *frameBufferPath = dict[@"frameBufferPath"];
NSNumber *isLastFrame = dict[@"isLastFrame"];
NSData *frameData;
if (data) {
frameData = data;
} else {
frameData = [NSData dataWithContentsOfFile:frameBufferPath options:0 error:nil];
}
Byte *bytes = (Byte *)frameData.bytes;
NSMutableArray *arrayM = [NSMutableArray array];
for (int i = 0; i < frameData.length; i++) {
int number = (int)bytes[i];
[arrayM addObject:@(number)];
}
NSDictionary *params = @{
@"method" : @"onFrameRecorded",
@"data" : @{
@"isLastFrame": isLastFrame,
@"buffer_id": frameBufferKey
}
};
NSDictionary *extDic = @{@"jsContextKey":frameBufferKey,@"jsContextValue":arrayM};
[recorder.frameInfoArray removeObject:dict];
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,extDic);
}
// [[FATExtCoreEventManager shareInstance] sendToServiceWithAppId:[[FATClient sharedClient] currentApplet].appId eventName:@"onRecorderManager" paramDict:params];
// 2.
recorder.frameState = FATFrameStateAlreadySent;
}
- (void)checkRecordState {
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
if (!appInfo.appId) {
return;
}
FATExtRecorder *recorder = [self.recorderDict objectForKey:appInfo.appId];
if ([recorder isRecording]) {
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateMicroPhone animate:YES];
}
}
}
#pragma mark - FATExtRecorderDelegate
- (void)extRecorder:(FATExtRecorder *)recorder
onFrameData:(NSData *)frameData
frameIndex:(NSInteger)frameIndex
isLastFrame:(BOOL)isLastFrame {
NSString *frameBufferKey = [recorder.recordFilePath lastPathComponent];
frameBufferKey = [frameBufferKey stringByDeletingPathExtension];
frameBufferKey = [frameBufferKey stringByAppendingFormat:@"_%ld", (long)frameIndex];
NSString *frameFileName = [frameBufferKey stringByAppendingPathExtension:recorder.recordFilePath.pathExtension];
NSString *frameBufferPath = [[recorder.recordFilePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:frameFileName];
NSDictionary *infoDict = @{@"frameIndex": @(frameIndex),
@"isLastFrame": @(isLastFrame),
@"frameBufferKey": frameBufferKey,
@"frameBufferPath": frameBufferPath
};
if ([NSThread isMainThread]) {
[recorder.frameInfoArray addObject:infoDict];
if (recorder.frameState == FATFrameStatePrepareToSend || recorder.waitToSendBuffer) {
//
[self sendFrameDataWithRecorder:recorder withFrameBufferData:frameData];
}
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[recorder.frameInfoArray addObject:infoDict];
if (recorder.frameState == FATFrameStatePrepareToSend || recorder.waitToSendBuffer) {
//
[self sendFrameDataWithRecorder:recorder withFrameBufferData:frameData];
}
});
}
}
- (void)extRecorder:(FATExtRecorder *)recorder onError:(NSError *)error {
NSString *msg = error.localizedDescription ? : @"fail";
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : msg},
};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
}
- (void)extRecorderDidCompletion:(FATExtRecorder *)recorder {
NSString *filePath = recorder.recordFilePath;
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
float duration = [FATExtUtil durtaionWithFileURL:fileURL];
long long fileSize = [FATExtUtil fileSizeWithFileURL:fileURL];
NSString *tempFilePath = [@"finfile://" stringByAppendingString:filePath.lastPathComponent];
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[result setValue:tempFilePath forKey:@"tempFilePath"];
[result setValue:@(duration) forKey:@"duration"];
[result setValue:@(fileSize) forKey:@"fileSize"];
NSDictionary *params = @{
@"method" : @"onStop",
@"data" : result,
};
[self.recorderDict removeObjectForKey:recorder.recorderId];
[self _clearAudioSession];
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
}
- (void)extRecorderBeginInterruption:(FATExtRecorder *)recorder {
NSDictionary *params = @{@"method" : @"onInterruptionBegin"};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
//
[self pauseRecordWithData:nil appletId:recorder.recorderId];
}
- (void)extRecorderEndInterruption:(FATExtRecorder *)recorder withOptions:(NSUInteger)flags {
NSDictionary *params = @{@"method" : @"onInterruptionEnd"};
if (recorder.eventCallBack) {
recorder.eventCallBack(0, @"onRecorderManager", params,nil);
}
}
@end

View File

@ -1,84 +0,0 @@
//
// FATMapViewDelegate.h
// FinAppletExt
//
// Created by on 2021/11/24.
// Copyright © 2021 finogeeks. All rights reserved.
//
#ifndef FATMapViewDelegate_h
#define FATMapViewDelegate_h
#import <UIKit/UIKit.h>
@protocol FATMapViewDelegate <NSObject>
@required
/// Subscribepage
/// eventName
/// resultDic
@property (nonatomic, copy) void(^eventCallBack)(NSString *eventName, NSDictionary *paramDic);
- (instancetype)initWithParam:(NSDictionary *)param mapPageId:(NSString *)pageId;
- (void)updateWithParam:(NSDictionary *)param;
///
- (NSDictionary *)fat_getCenter;
///
- (double)fat_getScale;
///
/// @param data
- (NSString *)fat_moveToLocation:(NSDictionary *)data;
///
/// @param data
- (void)fat_includePoints:(NSDictionary *)data;
///
- (NSDictionary *)fat_mapgetRegion;
///
- (NSDictionary *)fat_fromScreenLocation;
///
/// @param data
- (CGPoint)fat_toScreenLocation:(NSDictionary *)data;
///// app
- (void)fat_openMapApp:(NSDictionary *)data;
///
- (void)fat_addMarkers:(NSDictionary *)data;
///
- (void)fat_removeMarkers:(NSDictionary *)data;
///
- (BOOL)fat_translateMarker:(NSDictionary *)data;
/// 沿 marker
- (BOOL)fat_moveAlong:(NSDictionary *)data;
@optional
/// (0.25~0.75)[0.5, 0.5]
- (void)mapSetCenterOffset:(NSDictionary *)data;
- (void)fat_setLocMarkerIcon:(NSDictionary *)data;
/// sdknil
- (NSDictionary *)fat_getRotate;
///
- (NSDictionary *)fat_getskew;
/// customCallout
- (void)updateNativeMapMarkers:(NSDictionary *)param;
@end
#endif /* FATMapViewDelegate_h */

View File

@ -1,15 +0,0 @@
//
// FATExtHelper.h
// FinAppletExt
//
// Created by Haley on 2020/8/19.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface FATExtHelper : NSObject
+ (UIImage *)fat_ext_imageFromBundleWithName:(NSString *)imageName;
@end

View File

@ -1,21 +0,0 @@
//
// FATExtHelper.m
// FinAppletExt
//
// Created by Haley on 2020/8/19.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtHelper.h"
@implementation FATExtHelper
+ (UIImage *)fat_ext_imageFromBundleWithName:(NSString *)imageName {
NSString *bundleResourcePath = [NSBundle bundleForClass:[FATExtHelper class]].resourcePath;
NSString *assetPath = [bundleResourcePath stringByAppendingPathComponent:@"FinAppletExt.bundle"];
NSBundle *assetBundle = [NSBundle bundleWithPath:assetPath];
NSString *path = [[assetBundle bundlePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"/%@", imageName]];
return [UIImage imageWithContentsOfFile:path];
}
@end

View File

@ -1,53 +0,0 @@
//
// FATExtUtil.h
// FinAppletExt
//
// Created by Haley on 2021/1/25.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreLocation/CoreLocation.h>
@interface FATExtUtil : NSObject
+ (NSString *)tmpDirWithAppletId:(NSString *)appletId;
+ (NSString *)fat_md5WithBytes:(char *)bytes length:(NSUInteger)length;
+ (NSString *)jsonStringFromDict:(NSDictionary *)dict;
+ (NSString *)jsonStringFromArray:(NSArray *)array;
+ (NSString *)signFromDict:(NSDictionary *)dict;
+ (NSString *)realPathForFINFile:(NSString *)finfile appId:(NSString *)appId;
///
/// @param fileURL urlAVURLAsset .caf .aac .wav .mp3
+ (float)durtaionWithFileURL:(NSURL *)fileURL;
///
/// @param fileURL url
+ (long long)fileSizeWithFileURL:(NSURL *)fileURL;
/// userId
+ (NSString *)currentUserId;
/**
*/
+ (BOOL)currentProductIdentificationIsEmpty;
/**
*/
+ (NSString *)currentProductIdentification;
+ (NSString *)getAppName;
+ (void)getNearbyPlacesByCategory:(NSString *)category coordinates:(CLLocationCoordinate2D)coordinates radius:(NSInteger)radius token:(NSString *)token completion:(void (^)(NSDictionary *))completion;
+ (NSArray *)convertPlaceDictToArray:(NSDictionary*)dict;
@end

View File

@ -1,268 +0,0 @@
//
// FATExtUtil.m
// FinAppletExt
//
// Created by Haley on 2021/1/25.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import "FATExtUtil.h"
#import "FATExtFileManager.h"
#import "FATExtMapManager.h"
#import "fincore.h"
#import "FATMapPlace.h"
#import <FinApplet/FinApplet.h>
#import <CommonCrypto/CommonDigest.h>
#define FAT_EXT_FILE_SCHEMA @"finfile://"
@implementation FATExtUtil
+ (NSString *)tmpDirWithAppletId:(NSString *)appletId {
if (!appletId) {
return nil;
}
NSString *cacheDir = [FATExtFileManager appTempDirPath:appletId];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL flag = YES;
if (![fileManager fileExistsAtPath:cacheDir isDirectory:&flag]) {
[fileManager createDirectoryAtPath:cacheDir withIntermediateDirectories:YES attributes:nil error:nil];
}
return cacheDir;
}
+ (NSString *)fat_md5WithBytes:(char *)bytes length:(NSUInteger)length {
unsigned char result[16];
CC_MD5(bytes, (CC_LONG)length, result);
return [NSString stringWithFormat:
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]];
}
+ (NSString *)jsonStringFromDict:(NSDictionary *)dict {
if (!dict || ![dict isKindOfClass:[NSDictionary class]]) {
return nil;
}
NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
if (!data) {
return nil;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return jsonString;
}
+ (NSString *)jsonStringFromArray:(NSArray *)array {
if (!array || ![array isKindOfClass:[NSArray class]]) {
return nil;
}
NSData *data = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:nil];
if (!data) {
return nil;
}
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return jsonString;
}
+ (NSString *)signFromDict:(NSDictionary *)dict {
if (!dict || ![dict isKindOfClass:[NSDictionary class]]) {
return nil;
}
NSArray *keys = [dict allKeys];
NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch]; //
}];
NSString *plainText = @"";
for (NSString *key in sortedKeys) {
NSString *and = [plainText isEqualToString:@""] ? @"" : @"&";
NSString *value = [dict valueForKey:key];
// if ([value isKindOfClass:[NSDictionary class]]) {
// NSDictionary *dictValue = (NSDictionary *)value;
// value = [FATExtUtil jsonStringFromDict:dictValue];
// } else if ([key isKindOfClass:[NSArray class]]) {
// NSArray *arrayValue = (NSArray *)value;
// value = [FATExtUtil jsonStringFromArray:arrayValue];
// }
if ([key isEqualToString:@"sign"]) {
continue;
}
if ([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]]) {
NSString *append = [NSString stringWithFormat:@"%@%@=%@", and, key, value];
plainText = [plainText stringByAppendingString:append];
}
}
// NSLog(@"扩展:%@", plainText);
NSString *digest = [[[SDKCoreClient sharedInstance].finoLicenseService fin_messageDigest:plainText] uppercaseString];
NSData *data = [digest dataUsingEncoding:NSUTF8StringEncoding];
NSData *encodeData = [[SDKCoreClient sharedInstance].finoLicenseService fin_encodeSMContent:data];
NSString *sign = [[NSString alloc] initWithData:encodeData encoding:NSUTF8StringEncoding];
// NSLog(@"扩展sign%@", sign);
return sign;
}
///
/// @param fileURL urlAVURLAsset .caf .aac .wav .mp3
+ (float)durtaionWithFileURL:(NSURL *)fileURL {
NSDictionary *options = @{AVURLAssetPreferPreciseDurationAndTimingKey : @(YES)};
AVURLAsset *recordAsset = [AVURLAsset URLAssetWithURL:fileURL options:options];
// ms
CMTime durationTime = recordAsset.duration;
durationTime.value = durationTime.value;
float seconds = CMTimeGetSeconds(durationTime);
float duration = seconds * 1000;
return duration;
}
///
/// @param fileURL url
+ (long long)fileSizeWithFileURL:(NSURL *)fileURL {
// Byte
NSFileManager *manager = [NSFileManager defaultManager];
long long fileSize = [[manager attributesOfItemAtPath:fileURL.path error:nil] fileSize];
return fileSize;
}
+ (NSString *)currentUserId {
NSString *currentUserId = [FATClient sharedClient].config.currentUserId;
NSString *productIdentification = [FATClient sharedClient].config.productIdentification;
if (!currentUserId || currentUserId.length == 0) {
if ([NSString fat_isEmptyWithString:productIdentification]) {
currentUserId = @"finclip_default";
} else {
currentUserId = productIdentification;
}
}
return currentUserId;
}
+ (BOOL)currentProductIdentificationIsEmpty {
NSString *productIdentification = [FATClient sharedClient].config.productIdentification;
return [NSString fat_isEmptyWithString:productIdentification];
}
+ (NSString *)currentProductIdentification {
NSString *productIdentification = [FATClient sharedClient].config.productIdentification;
return productIdentification;
}
+ (NSString *)getAppName {
NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
NSString *appName = [infoDict valueForKey:@"CFBundleDisplayName"];
if (!appName) appName = [infoDict valueForKey:@"CFBundleName"];
if (!appName) appName = [infoDict valueForKey:@"CFBundleExecutable"];
return appName;
}
+ (void)getNearbyPlacesByCategory:(NSString *)category coordinates:(CLLocationCoordinate2D)coordinates radius:(NSInteger)radius token:(NSString *)token
completion:(void (^)(NSDictionary *))completion {
NSURL *url = [NSURL URLWithString:[self searchApiHost]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"GET";
if (token && [token length] > 0) {
NSDictionary *parameters = @{
@"key" : [FATExtMapManager shareInstance].googleMapApiKey,
@"pagetoken" : token
};
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in parameters) {
NSString *value = [NSString stringWithFormat:@"%@", parameters[key]];
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:value]];
}
urlComponents.queryItems = queryItems;
request.URL = urlComponents.URL;
} else {
NSDictionary *parameters = @{
@"key" : [FATExtMapManager shareInstance].placesApiKey,
@"radius" : @(radius),
@"location" : [NSString stringWithFormat:@"%f,%f", coordinates.latitude, coordinates.longitude],
@"type" : [category lowercaseString]
};
NSURLComponents *urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
NSMutableArray *queryItems = [NSMutableArray array];
for (NSString *key in parameters) {
NSString *value = [NSString stringWithFormat:@"%@", parameters[key]];
[queryItems addObject:[NSURLQueryItem queryItemWithName:key value:value]];
}
urlComponents.queryItems = queryItems;
request.URL = urlComponents.URL;
}
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.timeoutIntervalForRequest = 5.0;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"Error: %@", error);
completion(nil);
return;
}
if (data) {
NSError *jsonError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"Error: %@", jsonError);
completion(nil);
} else {
completion(json);
}
} else {
completion(nil);
}
}];
[task resume];
}
+ (NSArray *)convertPlaceDictToArray:(NSDictionary*)dict{
NSMutableArray *placeArrayM = [NSMutableArray array];
for (NSDictionary *dictItem in [dict objectForKey:@"results"]) {
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = dictItem[@"name"];
place.address = dictItem[@"vicinity"];
FATMapPlace *mark = [[FATMapPlace alloc] init];
NSDictionary *dict = dictItem[@"geometry"];
mark.name = dictItem[@"name"];
mark.address = dictItem[@"vicinity"];
double lat = [dict[@"location"][@"lat"] doubleValue];
double lng = [dict[@"location"][@"lng"] doubleValue];
place.location = [[CLLocation alloc] initWithLatitude:lat longitude:lng] ;
[placeArrayM addObject:place];
}
return placeArrayM;
}
+ (NSArray *)getCategories {
NSArray *list = @[@"Places",@"Bakery", @"Doctor", @"School", @"Taxi_stand", @"Hair_care", @"Restaurant", @"Pharmacy", @"Atm", @"Gym", @"Store", @"Spa"];
return list;
}
+ (NSString *)searchApiHost {
return @"https://maps.googleapis.com/maps/api/place/nearbysearch/json";
}
+ (NSString *)googlePhotosHost {
return @"https://maps.googleapis.com/maps/api/place/photo";
}
+ (NSString *)googlePlaceDetailsHost {
return @"https://maps.googleapis.com/maps/api/place/details/json";
}
@end

View File

@ -1,22 +0,0 @@
//
// FATLocationManager.h
// FinApplet
//
// Created by Haley on 2020/4/7.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface FATLocationManager : NSObject
@property (nonatomic, strong) CLLocation *location;
@property (nonatomic, strong) CLPlacemark *placemark;
+ (instancetype)manager;
- (void)updateLocation;
@end

View File

@ -1,99 +0,0 @@
//
// FATLocationManager.m
// FinApplet
//
// Created by Haley on 2020/4/7.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATLocationManager.h"
#import "FATWGS84ConvertToGCJ02.h"
#import "FATExtLocationManager.h"
static FATLocationManager *instance = nil;
@interface FATLocationManager () <CLLocationManagerDelegate>
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@end
@implementation FATLocationManager
+ (instancetype)manager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[FATLocationManager alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
- (void)updateLocation {
if (![FATExtLocationManager locationServicesEnabled]) {
return;
}
CLAuthorizationStatus status = [FATExtLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
status == kCLAuthorizationStatusAuthorizedAlways ||
status == kCLAuthorizationStatusNotDetermined) {
//
FATExtLocationManager *locationManager = [[FATExtLocationManager alloc] init];
self.locationManager = locationManager;
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager requestWhenInUseAuthorization];
[locationManager startUpdatingLocation];
} else if (status == kCLAuthorizationStatusDenied) {
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *newLocation = [locations firstObject];
//
if (![FATWGS84ConvertToGCJ02ForAMapView isLocationOutOfChina:[newLocation coordinate]]) {
//coord
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:[newLocation coordinate]];
newLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
}
self.location = newLocation;
[self.locationManager stopUpdatingLocation];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray<CLPlacemark *> *_Nullable placemarks, NSError *_Nullable error) {
if (error) {
return;
}
if (placemarks.count > 0) {
CLPlacemark *placemark = [placemarks objectAtIndex:0];
self.placemark = placemark;
// //
// NSString *province = placemark.administrativeArea;
// //
// NSLog(@"name,%@", placemark.name);
// //
// NSLog(@"thoroughfare,%@", placemark.thoroughfare);
// //
// NSLog(@"subThoroughfare,%@", placemark.subThoroughfare);
// //
// NSLog(@"locality,%@", placemark.locality);
// //
// NSLog(@"subLocality,%@", placemark.subLocality);
// //
// NSLog(@"country,%@", placemark.country);
}
}];
}
@end

View File

@ -1,19 +0,0 @@
//
// FATWGS84ConvertToGCJ02.h
// FinApplet
//
// Created by on 2018/8/9.
// Copyright © 2018 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface FATWGS84ConvertToGCJ02ForAMapView : NSObject
//
+ (BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location;
//GCJ-02
+ (CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc;
// gcj02wgs82
+ (CLLocationCoordinate2D)transformFromGCJToWGS:(CLLocationCoordinate2D)wgsLoc;
@end

View File

@ -1,135 +0,0 @@
//
// FATWGS84ConvertToGCJ02ForAMapView.m
// FinApplet
//
// Created by on 2018/8/9.
// Copyright © 2018 finogeeks. All rights reserved.
//
#import "FATWGS84ConvertToGCJ02.h"
#define RANGE_LON_MAX 137.8347
#define RANGE_LON_MIN 72.004
#define RANGE_LAT_MAX 55.8271
#define RANGE_LAT_MIN 0.8293
#define LAT_OFFSET_0(x,y) -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))
#define LAT_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
#define LAT_OFFSET_2 (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0
#define LAT_OFFSET_3 (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0
#define LON_OFFSET_0(x,y) 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x))
#define LON_OFFSET_1 (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0
#define LON_OFFSET_2 (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0
#define LON_OFFSET_3 (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0
#define jzA 6378245.0
#define jzEE 0.00669342162296594323
static const double fat_a = 6378245.0;
static const double fat_ee = 0.00669342162296594323;
@implementation FATWGS84ConvertToGCJ02ForAMapView
+ (CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc {
CLLocationCoordinate2D adjustLoc;
if ([self isLocationOutOfChina:wgsLoc]) {
adjustLoc = wgsLoc;
} else {
double adjustLat = [self transformLatWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double adjustLon = [self transformLonWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double radLat = wgsLoc.latitude / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - fat_ee * magic * magic;
double sqrtMagic = sqrt(magic);
adjustLat = (adjustLat * 180.0) / ((fat_a * (1 - fat_ee)) / (magic * sqrtMagic) * M_PI);
adjustLon = (adjustLon * 180.0) / (fat_a / sqrtMagic * cos(radLat) * M_PI);
adjustLoc.latitude = wgsLoc.latitude + adjustLat - 0.00039900; //
adjustLoc.longitude = wgsLoc.longitude + adjustLon;
}
return adjustLoc;
}
+ (CLLocationCoordinate2D)transformFromGCJToWGS:(CLLocationCoordinate2D)wgsLoc {
return [self gcj02Decrypt:wgsLoc.latitude gjLon:wgsLoc.longitude];
}
+ (CLLocationCoordinate2D)gcj02Decrypt:(double)gjLat gjLon:(double)gjLon {
CLLocationCoordinate2D gPt = [self gcj02Encrypt:gjLat bdLon:gjLon];
double dLon = gPt.longitude - gjLon;
double dLat = gPt.latitude - gjLat;
CLLocationCoordinate2D pt;
pt.latitude = gjLat - dLat;
pt.longitude = gjLon - dLon;
return pt;
}
+ (CLLocationCoordinate2D)gcj02Encrypt:(double)ggLat bdLon:(double)ggLon {
CLLocationCoordinate2D resPoint;
double mgLat;
double mgLon;
if ([self outOfChina:ggLat bdLon:ggLon]) {
resPoint.latitude = ggLat;
resPoint.longitude = ggLon;
return resPoint;
}
double dLat = [self transformLat:(ggLon - 105.0)bdLon:(ggLat - 35.0)];
double dLon = [self transformLon:(ggLon - 105.0) bdLon:(ggLat - 35.0)];
double radLat = ggLat / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - jzEE * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((jzA * (1 - jzEE)) / (magic * sqrtMagic) * M_PI);
dLon = (dLon * 180.0) / (jzA / sqrtMagic * cos(radLat) * M_PI);
mgLat = ggLat + dLat;
mgLon = ggLon + dLon;
resPoint.latitude = mgLat;
resPoint.longitude = mgLon;
return resPoint;
}
+ (BOOL)outOfChina:(double)lat bdLon:(double)lon {
if (lon < RANGE_LON_MIN || lon > RANGE_LON_MAX)
return true;
if (lat < RANGE_LAT_MIN || lat > RANGE_LAT_MAX)
return true;
return false;
}
+ (double)transformLat:(double)x bdLon:(double)y {
double ret = LAT_OFFSET_0(x, y);
ret += LAT_OFFSET_1;
ret += LAT_OFFSET_2;
ret += LAT_OFFSET_3;
return ret;
}
+ (double)transformLon:(double)x bdLon:(double)y {
double ret = LON_OFFSET_0(x, y);
ret += LON_OFFSET_1;
ret += LON_OFFSET_2;
ret += LON_OFFSET_3;
return ret;
}
//
+ (BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location {
if (location.longitude < 72.004 || location.longitude > 137.8347 || location.latitude < 0.8293 || location.latitude > 55.8271)
return YES;
return NO;
}
+ (double)transformLatWithX:(double)x withY:(double)y {
double lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x));
lat += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
lat += (20.0 * sin(y * M_PI) + 40.0 * sin(y / 3.0 * M_PI)) * 2.0 / 3.0;
lat += (160.0 * sin(y / 12.0 * M_PI) + 320 * sin(y * M_PI / 30.0)) * 2.0 / 3.0;
return lat;
}
+ (double)transformLonWithX:(double)x withY:(double)y {
double lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
lon += (20.0 * sin(6.0 * x * M_PI) + 20.0 * sin(2.0 * x * M_PI)) * 2.0 / 3.0;
lon += (20.0 * sin(x * M_PI) + 40.0 * sin(x / 3.0 * M_PI)) * 2.0 / 3.0;
lon += (150.0 * sin(x / 12.0 * M_PI) + 300.0 * sin(x / 30.0 * M_PI)) * 2.0 / 3.0;
return lon;
}
@end

View File

@ -1,17 +0,0 @@
//
// UIView+FATExtSafaFrame.h
// FinAppletExt
//
// Created by 耀 on 2023/5/25.
// Copyright © 2023 finogeeks. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (FATExtSafaFrame)
@end
NS_ASSUME_NONNULL_END

View File

@ -1,70 +0,0 @@
//
// UIView+FATExtSafaFrame.m
// FinAppletExt
//
// Created by 耀 on 2023/5/25.
// Copyright © 2023 finogeeks. All rights reserved.
//
#import "UIView+FATExtSafaFrame.h"
#import <objc/runtime.h>
@implementation UIView (FATExtSafaFrame)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method method1 = class_getInstanceMethod(self.class, @selector(setFrame:));
Method method2 = class_getInstanceMethod(self.class, @selector(fatSafe_setFrame:));
method_exchangeImplementations(method1, method2);
Method method3 = class_getInstanceMethod(self.class, @selector(setCenter:));
Method method4 = class_getInstanceMethod(self.class, @selector(fatSafe_setCenter:));
method_exchangeImplementations(method3, method4);
});
}
- (void)fatSafe_setFrame:(CGRect)frame{
CGRect unitFrame = frame;
if(isnan(unitFrame.origin.x)){
return;
}
if(isnan(unitFrame.origin.y)){
return;
}
if(isnan(unitFrame.size.width)){
return;
}
if(isnan(unitFrame.size.height)){
return;
}
@try {
[self fatSafe_setFrame:unitFrame];
} @catch (NSException *exception) {
} @finally {
}
}
- (void)fatSafe_setCenter:(CGPoint)center{
CGPoint unitCenter = center;
if(isnan(unitCenter.x)){
return;
}
if(isnan(unitCenter.y)){
return;
}
@try {
[self fatSafe_setCenter:unitCenter];
} @catch (NSException *exception) {
} @finally {
}
}
@end

View File

@ -1,21 +0,0 @@
//
// FATAnnotation.h
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface FATAnnotation : NSObject <MKAnnotation>
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *address;
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate;
@end

View File

@ -1,20 +0,0 @@
//
// FATAnnotation.m
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import "FATAnnotation.h"
@implementation FATAnnotation
- (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate {
if (self = [super init]) {
self.coordinate = coordinate;
}
return self;
}
@end

View File

@ -1,22 +0,0 @@
//
// FATExtChoosePoiViewController.h
// FinAppletExt
//
// Created by 耀 on 2021/12/8.
//
#import <UIKit/UIKit.h>
#import <FinApplet/FinApplet.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^SureBlock)(NSDictionary *locationInfo);
@interface FATExtChoosePoiViewController : FATUIViewController
@property (nonatomic, copy) dispatch_block_t cancelBlock;
@property (nonatomic, copy) SureBlock sureBlock;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,388 +0,0 @@
//
// FATExtChoosePoiViewController.m
// FinAppletExt
//
// Created by 耀 on 2021/12/8.
//
#import "FATExtChoosePoiViewController.h"
#import "FATLocationResultViewController.h"
#import "FATAnnotation.h"
#import "FATExtHelper.h"
#import "FATExtLocationManager.h"
#import "FATExtMapManager.h"
#import "FATExtUtil.h"
#import <CoreLocation/CoreLocation.h>
static NSString *kAnnotationId = @"FATAnnotationViewId";
static NSString *kUserAnnotationId = @"FATUserAnnotationViewId";
@interface FATExtChoosePoiViewController () <UITableViewDelegate, UITableViewDataSource, FATLocationResultDelegate, CLLocationManagerDelegate>
@property (nonatomic, strong) UIImageView *centerLocationView;
@property (nonatomic, strong) MKUserLocation *userLocation;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UIActivityIndicatorView *indicatorView;
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) FATLocationResultViewController *locationResultVC;
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, copy) NSString *cityName;
@end
@implementation FATExtChoosePoiViewController
- (NSMutableArray *)dataArray {
if (!_dataArray) {
_dataArray = [[NSMutableArray alloc] init];
}
return _dataArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.edgesForExtendedLayout = UIRectEdgeNone;
[self p_initNavigationBar];
[self p_initSubViews];
[self startLocation];
}
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
CGFloat width = self.view.bounds.size.width;
CGFloat height = self.view.bounds.size.height;
CGFloat searchBarH = self.searchController.searchBar.bounds.size.height;
CGFloat totalH = height - searchBarH;
self.centerLocationView.center = CGPointMake(width * 0.5, totalH * 0.5 * 0.5);
self.tableView.frame = CGRectMake(0, 0, width, height);
self.indicatorView.center = CGPointMake(width * 0.5, height * 0.5);
}
- (void)dealloc {
_searchController = nil;
_locationResultVC = nil;
}
#pragma mark - private method
- (void)p_initNavigationBar {
self.title = [[FATClient sharedClient] fat_localizedStringForKey:@"Location"];
NSString *cancel = [[FATClient sharedClient] fat_localizedStringForKey:@"Cancel"];
NSString *ok = [[FATClient sharedClient] fat_localizedStringForKey:@"OK"];
UIButton *cancelButton = [[UIButton alloc] init];
[cancelButton setTitle:cancel forState:UIControlStateNormal];
[cancelButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
[cancelButton addTarget:self action:@selector(cancelItemClick) forControlEvents:UIControlEventTouchUpInside];
UIButton *okButton = [[UIButton alloc] init];
[okButton setTitle:ok forState:UIControlStateNormal];
[okButton setTitleColor:[UIColor systemBlueColor] forState:UIControlStateNormal];
[okButton addTarget:self action:@selector(sureItemClick) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:cancelButton];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:okButton];
}
- (void)p_initSubViews {
[self p_initSearchBar];
self.centerLocationView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
self.centerLocationView.image = [FATExtHelper fat_ext_imageFromBundleWithName:@"fav_fileicon_loc90"];
[self.view addSubview:self.tableView];
[self.view addSubview:self.indicatorView];
[self.indicatorView startAnimating];
}
//
- (void)startLocation {
// CLog(@"--------开始定位");
self.locationManager = [[FATExtLocationManager alloc] init];
self.locationManager.delegate = self;
// ,
self.locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
[self.locationManager requestWhenInUseAuthorization];
self.locationManager.distanceFilter = 10.0f;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if ([error code] == kCLErrorDenied) {
// NSLog(@"访问被拒绝");
}
if ([error code] == kCLErrorLocationUnknown) {
// NSLog(@"无法获取位置信息");
}
}
//
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *newLocation = locations[0];
CLLocationCoordinate2D centerCoordinate = newLocation.coordinate;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:centerCoordinate.latitude longitude:centerCoordinate.longitude];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *array, NSError *error) {
CLPlacemark *placemark = nil;
if (!error) {
placemark = [array firstObject];
}
//
NSString *city = placemark.locality;
if (!city) {
city = placemark.administrativeArea;
}
self.cityName = city;
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(centerCoordinate, 1000, 1000);
request.region = region;
request.naturalLanguageQuery = [[FATClient sharedClient] fat_localizedStringForKey:@"Office Building"];
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
if([FATExtMapManager shareInstance].googleMapApiKey.length > 1){
[FATExtUtil getNearbyPlacesByCategory:request.naturalLanguageQuery coordinates: region.center radius:1000 token:@""
completion:^(NSDictionary * _Nonnull dict) {
self.dataArray = [[NSMutableArray alloc] initWithArray: [FATExtUtil convertPlaceDictToArray:dict]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicatorView stopAnimating];
[self addSpecialCity];
[self.tableView reloadData];
});
}];
}else {
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *_Nullable response, NSError *_Nullable error) {
//NSMutableArray *placeArrayM = [NSMutableArray array];
// if (placemark) {
// FATMapPlace *place = [[FATMapPlace alloc] init];
// place.name = placemark.name;
// place.address = placemark.thoroughfare;
// place.location = placemark.location;
// place.selected = YES;
// [self.dataArray addObject:place];
// }
for (MKMapItem *item in response.mapItems) {
if (!item.isCurrentLocation) {
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = item.placemark.name;
place.address = item.placemark.thoroughfare;
place.location = item.placemark.location;
[self.dataArray addObject:place];
}
}
[self.indicatorView stopAnimating];
[self addSpecialCity];
[self.tableView reloadData];
}];
}
}];
[manager stopUpdatingLocation];
}
- (void)p_initSearchBar {
_locationResultVC = [FATLocationResultViewController new];
_locationResultVC.delegate = self;
_locationResultVC.searchBarHeight = self.searchController.searchBar.bounds.size.height;
_searchController = [[UISearchController alloc] initWithSearchResultsController:_locationResultVC];
_searchController.searchResultsUpdater = _locationResultVC;
NSString *placeholder = [[FATClient sharedClient] fat_localizedStringForKey:@"Search nearby"];
_searchController.searchBar.placeholder = placeholder;
_searchController.searchBar.backgroundColor = [UIColor colorWithRed:239 / 255.0 green:239 / 255.0 blue:244 / 255.0 alpha:1];
UITextField *searchField;
if (@available(iOS 13.0, *)) {
searchField = _searchController.searchBar.searchTextField;
} else {
searchField = [_searchController.searchBar valueForKey:@"searchField"];
}
searchField.layer.borderColor = [UIColor colorWithRed:218 / 255.0 green:219 / 255.0 blue:233 / 255.0 alpha:1].CGColor;
self.tableView.tableHeaderView = _searchController.searchBar;
}
#pragma mark - click events
- (void)cancelItemClick {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
if (self.cancelBlock) {
self.cancelBlock();
}
}
- (void)sureItemClick {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
FATMapPlace *selectPlace = nil;
for (FATMapPlace *place in self.dataArray) {
if (place.selected) {
selectPlace = place;
break;
}
}
NSString *type;
CLLocationCoordinate2D coordinate = selectPlace.location.coordinate;
NSMutableDictionary *locationInfo = [[NSMutableDictionary alloc] initWithDictionary:@{@"latitude" : [NSString stringWithFormat:@"%@", @(coordinate.latitude)],
@"longitude" : [NSString stringWithFormat:@"%@", @(coordinate.longitude)]}];
if ([selectPlace.name isEqualToString:[[FATClient sharedClient] fat_localizedStringForKey:@"Don't show location"]]) {
type = @"0";
} else if (!selectPlace.address) {
type = @"1";
[locationInfo setValue: selectPlace.name ?: @"" forKey:@"city"];
} else {
type = @"2";
[locationInfo setValue: selectPlace.address ?: @"" forKey:@"name"];
[locationInfo setValue: selectPlace.name ?: @"" forKey:@"address"];
}
[locationInfo setValue:type forKey:@"type"];
if (self.sureBlock) {
self.sureBlock(locationInfo);
}
}
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
_tableView.dataSource = self;
_tableView.delegate = self;
_tableView.backgroundColor = [UIColor whiteColor];
_tableView.tableFooterView = [UIView new];
}
return _tableView;
}
- (UIActivityIndicatorView *)indicatorView {
if (!_indicatorView) {
_indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_indicatorView.hidesWhenStopped = YES;
}
return _indicatorView;
}
#pragma mark - FATLocationResultDelegate
- (void)selectedLocationWithLocation:(FATMapPlace *)place {
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
NSString *type;
CLLocationCoordinate2D coordinate = place.location.coordinate;
NSMutableDictionary *locationInfo = [[NSMutableDictionary alloc] initWithDictionary:@{@"latitude" : [NSString stringWithFormat:@"%@", @(coordinate.latitude)],
@"longitude" : [NSString stringWithFormat:@"%@", @(coordinate.longitude)]}];
if ([place.name isEqualToString:[[FATClient sharedClient] fat_localizedStringForKey:@"Don't show location"]]) {
type = @"0";
} else if (!place.address) {
type = @"1";
[locationInfo setValue: place.name ?: @"" forKey:@"city"];
} else {
type = @"2";
[locationInfo setValue: place.address ?: @"" forKey:@"name"];
[locationInfo setValue: place.name ?: @"" forKey:@"address"];
}
[locationInfo setValue:type forKey:@"type"];
if (self.sureBlock) {
self.sureBlock(locationInfo);
}
}
#pragma mark - MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
if (!self.userLocation) {
_userLocation = userLocation;
CLLocationCoordinate2D center = userLocation.location.coordinate;
if (center.latitude > 0 && center.longitude > 0) {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, 1000, 1000);
mapView.centerCoordinate = center;
mapView.region = region;
self.locationResultVC.region = region;
}
}
}
//
- (void)addSpecialCity {
//
NSMutableArray *deleteArray = [[NSMutableArray alloc] init];
for (FATMapPlace *place in self.dataArray) {
if ([place.name isEqualToString:[[FATClient sharedClient] fat_localizedStringForKey:@"Don't show location"]]) {
[deleteArray insertObject:place atIndex:0];
}
if (place.name && !place.address) {
[deleteArray insertObject:place atIndex:0];
}
}
if (deleteArray.count != 0) {
[self.dataArray removeObjectsInArray:deleteArray];
}
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = self.cityName;
place.location = place.location;
place.selected = NO;
[self.dataArray insertObject:place atIndex:0];
FATMapPlace *NoPlace = [[FATMapPlace alloc] init];
NoPlace.name = [[FATClient sharedClient] fat_localizedStringForKey:@"Don't show location"];
NoPlace.selected = NO;
[self.dataArray insertObject:NoPlace atIndex:0];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = @"identifer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifer];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.detailTextLabel.textColor = [UIColor grayColor];
}
FATMapPlace *place = self.dataArray[indexPath.row];
if ([place.name isEqualToString:[[FATClient sharedClient] fat_localizedStringForKey:@"Don't show location"]]) {
cell.textLabel.textColor = [UIColor fat_colorWithRGBHexString:@"0066ff" alpha:1.0];
} else {
if (@available(iOS 13.0, *)) {
cell.textLabel.textColor = UIColor.labelColor;
} else {
cell.textLabel.textColor = UIColor.blackColor;
}
}
cell.textLabel.text = place.name;
cell.detailTextLabel.text = place.address;
if (place.selected) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
for (FATMapPlace *place in self.dataArray) {
place.selected = NO;
}
FATMapPlace *place = self.dataArray[indexPath.row];
place.selected = YES;
[self.tableView reloadData];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(place.location.coordinate, 1000, 1000);
self.locationResultVC.region = region;
}
@end

View File

@ -1,32 +0,0 @@
//
// FATExtSliderView.h
// FinAppletGDMap
//
// Created by 耀 on 2021/12/13.
//
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "FATMapPlace.h"
#define fatKScreenWidth ([UIScreen mainScreen].bounds.size.width)
#define fatKScreenHeight ([UIScreen mainScreen].bounds.size.height)
NS_ASSUME_NONNULL_BEGIN
typedef void (^SelectItemBlock)(FATMapPlace *locationInfo);
typedef void (^TopDistance)(float height, BOOL isTopOrBottom);
@interface FATExtSliderView : UIView
@property (nonatomic, copy) SelectItemBlock selectItemBlock;
@property (nonatomic, assign) float topH; //
@property (nonatomic, copy) TopDistance topDistance;
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray<FATMapPlace *> *poiInfoListArray;
- (void)updateSearchFrameWithColcationCoordinate:(CLLocationCoordinate2D)coord;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,365 +0,0 @@
//
// FATExtSliderView.m
// FinAppletGDMap
//
// Created by 耀 on 2021/12/13.
//
#import "FATExtSliderView.h"
#import "UIView+FATExtFrame.h"
#import <FinApplet/FinApplet.h>
#import "UIView+FATExtSafaFrame.h"
#import "FATExtUtil.h"
#import "FATExtMapManager.h"
@interface FATExtSliderView () <UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate, UISearchControllerDelegate, UISearchBarDelegate>
@property (nonatomic, assign) float bottomH; //
@property (nonatomic, assign) float stop_y; //tableView
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) NSMutableArray<FATMapPlace *> *tempPoiInfoListArray;
@property (nonatomic, assign) NSInteger selectNumber;
@property (nonatomic, strong) UISearchController *search;
@property (nonatomic, assign) CLLocationCoordinate2D locationCoordinate;
@property (nonatomic, assign) NSInteger pageIndex;
@property (nonatomic, strong) NSString *cityString;
@property (nonatomic, assign) MKCoordinateRegion region;
@end
@implementation FATExtSliderView
- (NSMutableArray<FATMapPlace *> *)poiInfoListArray {
if (!_poiInfoListArray) {
_poiInfoListArray = [[NSMutableArray alloc] init];
}
return _poiInfoListArray;
}
- (NSMutableArray<FATMapPlace *> *)tempPoiInfoListArray {
if (!_tempPoiInfoListArray) {
_tempPoiInfoListArray = [[NSMutableArray alloc] init];
}
return _tempPoiInfoListArray;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setUI];
}
return self;
}
- (void)setUI {
self.backgroundColor = [UIColor systemGrayColor];
self.bottomH = self.top;
self.pageIndex = 0;
self.selectNumber = 0;
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
panGestureRecognizer.delegate = self;
[self addGestureRecognizer:panGestureRecognizer];
[self creatUI];
}
- (void)creatUI {
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, fatKScreenWidth, self.frame.size.height) style:UITableViewStylePlain];
self.tableView.backgroundColor = [UIColor whiteColor];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.showsVerticalScrollIndicator = NO;
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.bounces = NO;
if (@available(iOS 11.0, *)) {
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
// Fallback on earlier versions
}
[self addSubview:self.tableView];
[self.tableView registerNib:[UINib nibWithNibName:@"SlideTableViewCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"SlideTableViewCell"];
self.tableView.tableHeaderView = self.searchController.searchBar;
self.search.delegate = self;
}
- (void)getData {
CLLocationCoordinate2D centerCoordinate = self.locationCoordinate;
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
CLLocation *location = [[CLLocation alloc] initWithLatitude:centerCoordinate.latitude longitude:centerCoordinate.longitude];
[geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *array, NSError *error) {
CLPlacemark *placemark = nil;
if (!error) {
placemark = [array firstObject];
}
MKCoordinateSpan span = MKCoordinateSpanMake(centerCoordinate.latitude, centerCoordinate.longitude);
MKCoordinateRegion newRegion = MKCoordinateRegionMake(centerCoordinate, span);
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.region;
request.naturalLanguageQuery = @"Place";
CLLocationCoordinate2D destCenter = self.region.center;
if(destCenter.latitude == 0){
destCenter = centerCoordinate;
}
if([FATExtMapManager shareInstance].googleMapApiKey.length > 1){
[FATExtUtil getNearbyPlacesByCategory:@"All" coordinates:destCenter radius:1000 token:@""
completion:^(NSDictionary * _Nonnull dict) {
NSMutableArray *placeArrayM = [NSMutableArray array];
// if (placemark) {
// FATMapPlace *place = [[FATMapPlace alloc] init];
// place.name = placemark.name;
// place.address = placemark.thoroughfare;
// place.location = placemark.location;
// place.selected = YES;
// [placeArrayM addObject:place];
// }
[placeArrayM addObjectsFromArray:[FATExtUtil convertPlaceDictToArray:dict]];
self.poiInfoListArray = [[NSMutableArray alloc] initWithArray: placeArrayM];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
}else{
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *_Nullable response, NSError *_Nullable error) {
NSMutableArray *placeArrayM = [NSMutableArray array];
for (MKMapItem *item in response.mapItems) {
if (!item.isCurrentLocation) {
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = item.placemark.name;
place.address = item.placemark.thoroughfare;
place.location = item.placemark.location;
[placeArrayM addObject:place];
}
}
self.poiInfoListArray = [[NSMutableArray alloc] initWithArray:placeArrayM];
[self.tableView reloadData];
}];
}
}];
}
- (void)updateSearchFrameWithColcationCoordinate:(CLLocationCoordinate2D)coord {
// struct CLLocationCoordinate2D my2D = {40.0, 115.0};//self.locationCoordinate
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(self.locationCoordinate, 1000, 1000);
self.region = region;
self.locationCoordinate = coord;
[self.poiInfoListArray removeAllObjects];
[self.tableView reloadData];
[self getData];
}
- (void)p_searchLocationsWithSearchText:(NSString *)searchText {
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.region;
request.naturalLanguageQuery = searchText;
CLLocationCoordinate2D destCenter = self.region.center;
if(destCenter.latitude == 0){
destCenter = self.locationCoordinate;
}
if([FATExtMapManager shareInstance].googleMapApiKey.length > 1){
[FATExtUtil getNearbyPlacesByCategory:searchText coordinates:destCenter radius:1000 token:@""
completion:^(NSDictionary * _Nonnull dict) {
self.poiInfoListArray = [[NSMutableArray alloc] initWithArray: [FATExtUtil convertPlaceDictToArray:dict]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
}else { MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *_Nullable response, NSError *_Nullable error) {
NSMutableArray *placeArrayM = [NSMutableArray array];
for (MKMapItem *item in response.mapItems) {
if (!item.isCurrentLocation) {
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = item.placemark.name;
place.address = item.placemark.thoroughfare;
place.location = item.placemark.location;
[placeArrayM addObject:place];
}
}
self.poiInfoListArray = [[NSMutableArray alloc] initWithArray:placeArrayM];
[self.tableView reloadData];
}];
}
}
#pragma mark -
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat currentPostion = scrollView.contentOffset.y;
self.stop_y = currentPostion;
if (self.top > self.topH) {
[scrollView setContentOffset:CGPointMake(0, 0)];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
- (void)panAction:(UIPanGestureRecognizer *)pan {
//
CGPoint point = [pan translationInView:self];
// stop_ytableviewtableview0
if (self.stop_y > 0) {
// 0
[pan setTranslation:CGPointMake(0, 0) inView:self];
return;
}
// self.top
self.top += point.y;
if (self.top < self.topH) {
self.top = self.topH;
}
// self.bottomH
if (self.top > self.bottomH) {
self.top = self.bottomH;
}
//
//
if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
//
CGPoint velocity = [pan velocityInView:self];
CGFloat speed = 350;
if (velocity.y < -speed) {
[self goTop];
[pan setTranslation:CGPointMake(0, 0) inView:self];
return;
} else if (velocity.y > speed) {
[self goBack];
[pan setTranslation:CGPointMake(0, 0) inView:self];
return;
}
if (self.top > fatKScreenHeight / 2) {
[self goBack];
} else {
[self goTop];
}
}
[pan setTranslation:CGPointMake(0, 0) inView:self];
if (self.top != self.bottomH) {
if (!isnan(point.y)) {
if (self.topDistance) {
self.topDistance(point.y, false);
}
}
}
}
- (void)goTop {
if (self.top != self.bottomH) {
if (self.topDistance) {
if (!isnan(self.topH)) {
self.topDistance(self.topH, true);
}
}
}
[UIView animateWithDuration:0.5 animations:^{
self.top = self.topH;
} completion:^(BOOL finished){
}];
}
- (void)goBack {
if (self.topDistance) {
if (!isnan(self.bottomH)) {
self.topDistance(self.bottomH, true);
}
}
[UIView animateWithDuration:0.5 animations:^{
self.top = self.bottomH;
} completion:^(BOOL finished){
// self.tableView.userInteractionEnabled = NO;
}];
}
#pragma mark - UITableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.poiInfoListArray.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = @"identifer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifer];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.detailTextLabel.textColor = [UIColor grayColor];
}
cell.textLabel.text = self.poiInfoListArray[indexPath.row].name;
cell.detailTextLabel.text = self.poiInfoListArray[indexPath.row].address;
if (indexPath.row == self.selectNumber) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
self.selectNumber = indexPath.row;
[tableView reloadData];
FATMapPlace *poiInfo = self.poiInfoListArray[indexPath.row];
if (self.selectItemBlock) {
self.selectItemBlock(poiInfo);
}
}
#pragma mark - UISearchResultsUpdating
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[self goTop];
self.tempPoiInfoListArray = [[NSMutableArray alloc] initWithArray:self.poiInfoListArray];
[self.poiInfoListArray removeAllObjects];
[self.tableView reloadData];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
self.selectNumber = -1;
NSString *searchString = self.searchController.searchBar.text;
[self p_searchLocationsWithSearchText:searchString];
self.searchController.active = NO;
[self goBack];
self.searchController.searchBar.text = searchString;
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
[self goBack];
self.poiInfoListArray = [[NSMutableArray alloc] initWithArray:self.tempPoiInfoListArray];
[self.tableView reloadData];
}
- (UISearchController *)searchController {
if (!_searchController) {
_searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
_searchController.searchBar.delegate = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.hidesNavigationBarDuringPresentation = NO;
_searchController.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
_searchController.searchBar.frame = CGRectMake(0, 0, fatKScreenWidth, 44);
NSString *placeholder = [[FATClient sharedClient] fat_localizedStringForKey:@"Search for location"];
_searchController.searchBar.placeholder = placeholder;
}
return _searchController;
}
@end

View File

@ -1,27 +0,0 @@
//
// FATLocationResultViewController.h
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <FinApplet/FinApplet.h>
#import "FATMapPlace.h"
@protocol FATLocationResultDelegate <NSObject>
- (void)selectedLocationWithLocation:(FATMapPlace *)place;
@end
@interface FATLocationResultViewController : FATUIViewController <UISearchResultsUpdating>
@property (nonatomic, assign) MKCoordinateRegion region;
@property (nonatomic, weak) id<FATLocationResultDelegate> delegate;
@property (nonatomic, assign) NSInteger searchBarHeight;
@end

View File

@ -1,124 +0,0 @@
//
// FATLocationResultViewController.m
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import "FATLocationResultViewController.h"
#import "FATExtMapManager.h"
#import "FATExtUtil.h"
@interface FATLocationResultViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, copy) NSArray<FATMapPlace *> *places;
@property (nonatomic, strong) FATMapPlace *selectedPlace;
@end
@implementation FATLocationResultViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self p_initSubViews];
}
#pragma mark - private method
- (void)p_initSubViews {
self.edgesForExtendedLayout = UIRectEdgeNone;
CGFloat width = self.view.bounds.size.width;
CGFloat height = self.view.bounds.size.height;
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, self.searchBarHeight, width, height - self.searchBarHeight - 60) style:UITableViewStylePlain];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.rowHeight = 60;
[self.view addSubview:self.tableView];
}
- (void)p_searchLocationsWithSearchText:(NSString *)searchText {
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.region = self.region;
request.naturalLanguageQuery = searchText;
MKLocalSearch *localSearch = [[MKLocalSearch alloc] initWithRequest:request];
if([FATExtMapManager shareInstance].googleMapApiKey.length > 1){
[FATExtUtil getNearbyPlacesByCategory:searchText coordinates:self.region.center radius:1000 token:@""
completion:^(NSDictionary * _Nonnull dict) {
self.places = [[FATExtUtil convertPlaceDictToArray:dict] copy];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
}else{[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *_Nullable response, NSError *_Nullable error) {
NSMutableArray *placeArrayM = [NSMutableArray array];
for (MKMapItem *item in response.mapItems) {
if (!item.isCurrentLocation) {
FATMapPlace *place = [[FATMapPlace alloc] init];
place.name = item.placemark.name;
place.address = item.placemark.thoroughfare;
place.location = item.placemark.location;
[placeArrayM addObject:place];
}
}
self.places = [placeArrayM copy];
[self.tableView reloadData];
}];
}
}
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSString *searchString = searchController.searchBar.text;
[self p_searchLocationsWithSearchText:searchString];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.places.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = @"placeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifer];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifer];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.detailTextLabel.textColor = [UIColor grayColor];
}
FATMapPlace *place = self.places[indexPath.row];
cell.textLabel.text = place.name;
cell.detailTextLabel.text = place.address;
if (place.selected) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
for (FATMapPlace *place in self.places) {
place.selected = NO;
}
FATMapPlace *place = self.places[indexPath.row];
place.selected = YES;
[self.tableView reloadData];
if (self.delegate && [self.delegate respondsToSelector:@selector(selectedLocationWithLocation:)]) {
[self.delegate selectedLocationWithLocation:place];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
@end

View File

@ -1,23 +0,0 @@
//
// FATMapPlace.h
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CLPlacemark.h>
@interface FATMapPlace : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *address;
//@property (nonatomic, strong) CLPlacemark *placemark;
@property (nonatomic, strong) CLLocation *location;
@property (nonatomic, assign) BOOL selected;
@end

View File

@ -1,13 +0,0 @@
//
// FATMapPlace.m
// AppletDemo
//
// Created by Haley on 2020/4/17.
// Copyright © 2020 weidian. All rights reserved.
//
#import "FATMapPlace.h"
@implementation FATMapPlace
@end

View File

@ -1,24 +0,0 @@
//
// FATMapViewController.h
// AppletDemo
//
// Created by Haley on 2020/4/16.
// Copyright © 2020 weidian. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <FinApplet/FinApplet.h>
typedef void (^SureBlock)(NSDictionary *locationInfo);
@interface FATMapViewController : FATUIViewController
@property (nonatomic, copy) dispatch_block_t cancelBlock;
@property (nonatomic, copy) SureBlock sureBlock;
///
@property (nonatomic, strong) NSString *latitude;
///
@property (nonatomic, strong) NSString *longitude;
@end

View File

@ -1,359 +0,0 @@
//
// FATMapViewController.m
// AppletDemo
//
// Created by Haley on 2020/4/16.
// Copyright © 2020 weidian. All rights reserved.
//
#import "FATMapViewController.h"
#import "FATLocationResultViewController.h"
#import "FATAnnotation.h"
#import "FATExtHelper.h"
#import "FATExtSliderView.h"
#import "FATWGS84ConvertToGCJ02.h"
#import "FATExtLocationManager.h"
#import <MapKit/MapKit.h>
#import "UIView+FATExtSafaFrame.h"
#define fatKScreenWidth ([UIScreen mainScreen].bounds.size.width)
#define fatKScreenHeight ([UIScreen mainScreen].bounds.size.height)
static NSString *kAnnotationId = @"FATAnnotationViewId";
static NSString *kUserAnnotationId = @"FATUserAnnotationViewId";
@interface FATMapViewController () <MKMapViewDelegate, CLLocationManagerDelegate, FATLocationResultDelegate>
@property (nonatomic, strong) MKMapView *mapView;
@property (nonatomic, strong) MKUserLocation *userLocation;
@property (nonatomic, strong) UIButton *returnButton;
@property (nonatomic, strong) UIButton *determineButton;
@property (nonatomic, strong) UIButton *positionButton;
@property (nonatomic, strong) FATExtSliderView *slideView;
@property (nonatomic, strong) FATMapPlace *poiInfo;
@property (nonatomic, strong) MKPointAnnotation *centerAnnotation;
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@end
@implementation FATMapViewController
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// [self.navigationController setNavigationBarHidden:NO animated:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear: animated];
_mapView.showsUserLocation = NO;
_mapView.userTrackingMode = MKUserTrackingModeNone;
[_mapView.layer removeAllAnimations];
[_mapView removeAnnotations:self.mapView.annotations];
[_mapView removeOverlays:self.mapView.overlays];
[_mapView removeFromSuperview];
_mapView.delegate = nil;
_mapView = nil;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.edgesForExtendedLayout = UIRectEdgeNone;
[self p_initSubViews];
[self settingMapCenter];
}
- (void)dealloc {
_mapView.showsUserLocation = NO;
_mapView.userTrackingMode = MKUserTrackingModeNone;
[_mapView.layer removeAllAnimations];
[_mapView removeAnnotations:self.mapView.annotations];
[_mapView removeOverlays:self.mapView.overlays];
[_mapView removeFromSuperview];
_mapView.delegate = nil;
_mapView = nil;
}
- (void)p_initSubViews {
//
BOOL isDark = false;
if (@available(iOS 12.0, *)) {
isDark = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark);
}
self.view.backgroundColor = isDark ? UIColor.blackColor : UIColor.whiteColor;
[self.view addSubview:self.mapView];
self.mapView.frame = CGRectMake(0, 0, fatKScreenWidth, fatKScreenHeight - 200);
self.centerAnnotation = [[MKPointAnnotation alloc] init];
self.centerAnnotation.coordinate = self.mapView.centerCoordinate;
[self.mapView addAnnotation:self.centerAnnotation];
CGFloat top = [UIView fat_statusHeight];
self.returnButton = [[UIButton alloc] initWithFrame:CGRectMake(16, top, 57, 32)];
[self.returnButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_back_n"] forState:UIControlStateNormal];
[self.returnButton addTarget:self action:@selector(cancelItemClick) forControlEvents:UIControlEventTouchUpInside];
[self.mapView addSubview:self.returnButton];
self.determineButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 16 - 57, top, 57, 32)];
NSString *ok = [[FATClient sharedClient] fat_localizedStringForKey:@"OK"];
[self.determineButton setTitle:ok forState:UIControlStateNormal];
[self.determineButton setTitleColor:[UIColor colorWithRed:255 / 255.0 green:255 / 255.0 blue:255 / 255.0 alpha:1 / 1.0] forState:UIControlStateNormal];
[self.determineButton setBackgroundColor:[UIColor colorWithRed:64 / 255.0 green:158 / 255.0 blue:255 / 255.0 alpha:1 / 1.0]];
[self.determineButton addTarget:self action:@selector(sureItemClick) forControlEvents:UIControlEventTouchUpInside];
self.determineButton.titleLabel.font = [UIFont systemFontOfSize:17];
[self.mapView addSubview:self.determineButton];
self.positionButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 73, fatKScreenHeight - 260, 45, 45)];
if (isDark) {
[self.positionButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_dn"] forState:UIControlStateNormal];
[self.positionButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_dp"] forState:UIControlStateHighlighted];
self.mapView.mapType = MKMapTypeStandard;
} else {
[self.positionButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_ln"] forState:UIControlStateNormal];
[self.positionButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_lp"] forState:UIControlStateHighlighted];
self.mapView.mapType = MKMapTypeStandard;
}
[self.positionButton addTarget:self action:@selector(locationOnClick) forControlEvents:UIControlEventTouchUpInside];
[self.mapView addSubview:self.positionButton];
__weak typeof(self) weakSelf = self;
self.slideView = [[FATExtSliderView alloc] initWithFrame:CGRectMake(0, fatKScreenHeight - 200, fatKScreenWidth, fatKScreenHeight - 250)];
self.slideView.backgroundColor = isDark ? UIColor.blackColor : UIColor.whiteColor;
self.slideView.tableView.backgroundColor = isDark ? UIColor.blackColor : UIColor.whiteColor;
self.slideView.topH = 300;
self.slideView.selectItemBlock = ^(FATMapPlace *locationInfo) {
CLLocationCoordinate2D centerCoord = {locationInfo.location.coordinate.latitude, locationInfo.location.coordinate.longitude};
weakSelf.poiInfo = locationInfo;
[UIView animateWithDuration:1 animations:^{
weakSelf.centerAnnotation.coordinate = centerCoord;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(centerCoord, 1000, 1000);
weakSelf.mapView.centerCoordinate = centerCoord;
weakSelf.mapView.region = region;
}];
};
if ([self.latitude isEqualToString:@"nil"] || [self.longitude isEqualToString:@"nil"] || (!self.latitude && !self.longitude)) {
[self startStandardUpdates];
} else {
CLLocationCoordinate2D centerCoord = {[self.latitude doubleValue], [self.longitude doubleValue]};
self.mapView.centerCoordinate = centerCoord;
[self.slideView updateSearchFrameWithColcationCoordinate:self.mapView.centerCoordinate];
}
__block float heights = fatKScreenHeight - 200;
__block float positionButtonY = fatKScreenHeight - 260;
self.slideView.topDistance = ^(float height, BOOL isTopOrBottom) {
if (!isTopOrBottom) {
heights += height;
positionButtonY += height;
} else {
heights = height;
positionButtonY = height;
}
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.mapView.frame = CGRectMake(0, 0, fatKScreenWidth, heights);
weakSelf.positionButton.frame = CGRectMake(self.view.frame.size.width - 73, positionButtonY > fatKScreenHeight - 260 ? fatKScreenHeight - 260 : positionButtonY, 45, 45);
if (heights + weakSelf.slideView.frame.size.height < fatKScreenHeight) {
weakSelf.mapView.frame = CGRectMake(0, 0, fatKScreenWidth, fatKScreenHeight - weakSelf.slideView.frame.size.height);
weakSelf.positionButton.frame = CGRectMake(self.view.frame.size.width - 73, fatKScreenHeight - 260, 45, 45);
}
});
};
[self.view addSubview:self.slideView];
}
- (void)locationOnClick {
[self startStandardUpdates];
}
- (void)startStandardUpdates {
// if (![FATExtLocationManager locationServicesEnabled]) {
// return;
// }
CLAuthorizationStatus status = [FATExtLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
status == kCLAuthorizationStatusAuthorizedAlways ||
status == kCLAuthorizationStatusNotDetermined) {
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
}
}
- (void)settingMapCenter {
if ([NSString fat_isEmptyWithString:self.latitude] || [NSString fat_isEmptyWithString:self.longitude]) {
return;
}
double LongitudeDelta = [self fat_getLongitudeDelta:14.00];
// double LatitudeDelta = LongitudeDelta * 2;
CLLocationCoordinate2D centerCoord = {[self judgeLatition:[self.latitude doubleValue]], [self judgeLongitude:[self.longitude doubleValue]]};
MKCoordinateRegion region = MKCoordinateRegionMake(centerCoord, MKCoordinateSpanMake(LongitudeDelta, LongitudeDelta));
CLLocationCoordinate2D center = region.center;
MKCoordinateSpan span = region.span;
if (center.latitude < -90 || center.latitude > 90 ||
center.longitude < -180 || center.longitude > 180) {
return ;
}
if (span.latitudeDelta <= 0 || span.longitudeDelta <= 0) {
return ;
}
[self.mapView setRegion:region animated:YES];
}
#pragma mark - click events
- (void)cancelItemClick {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
if (self.cancelBlock) {
self.cancelBlock();
}
}
- (void)sureItemClick {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
if (self.poiInfo == nil && self.slideView.poiInfoListArray.count > 0) {
self.poiInfo = self.slideView.poiInfoListArray.firstObject;
}
CLLocationCoordinate2D coordinate = self.poiInfo.location.coordinate;
NSDictionary *locationInfo = @{@"name" : self.poiInfo.name ?: @"",
@"address" : self.poiInfo.address ?: @"",
@"latitude" : @(coordinate.latitude),
@"longitude" : @(coordinate.longitude)};
if (self.sureBlock) {
self.sureBlock(locationInfo);
}
}
#pragma mark - FATLocationResultDelegate
- (void)selectedLocationWithLocation:(FATMapPlace *)place {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(place.location.coordinate, 1000, 1000);
self.mapView.centerCoordinate = place.location.coordinate;
self.mapView.region = region;
}
#pragma mark - MKMapViewDelegate
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
if (!self.userLocation) {
_userLocation = userLocation;
CLLocationCoordinate2D center = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:userLocation.location.coordinate];
if (center.latitude > 0 && center.longitude > 0) {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center, 1000, 1000);
if ([NSString fat_isEmptyWithString:self.latitude] || [NSString fat_isEmptyWithString:self.longitude]) {
mapView.centerCoordinate = center;
mapView.region = region;
[self.mapView setRegion:region animated:YES];
self.centerAnnotation.coordinate = center;
}
}
[self.slideView updateSearchFrameWithColcationCoordinate:center];
}
}
/**
*
*
* @param manager
* @param locations
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations firstObject];
//
CLLocationCoordinate2D theCoordinate = location.coordinate;
//
MKCoordinateRegion theRegion;
theRegion.center = theCoordinate;
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:theCoordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(coord, 1000, 1000);
[self.mapView setRegion:region animated:YES];
self.centerAnnotation.coordinate = coord;
[self.locationManager stopUpdatingLocation];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CLLocationCoordinate2D centerCoordinate = self.mapView.centerCoordinate;
// CLLocationCoordinate2D centerCoordinate = self.centerAnnotation.coordinate;
[self.slideView updateSearchFrameWithColcationCoordinate:centerCoordinate];
}
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
CLLocationCoordinate2D centerCoordinate = mapView.centerCoordinate;
[UIView animateWithDuration:1 animations:^{
self.centerAnnotation.coordinate = centerCoordinate;
}];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString *ID = @"anno";
MKPinAnnotationView *annoView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:ID];
if (annoView == nil) {
annoView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:ID];
//
annoView.canShowCallout = YES;
// 绿
}
return annoView;
}
- (double)fat_getLongitudeDelta:(double)scale {
double longitudeDelta = (360 * self.mapView.frame.size.width / 256.0 / pow(2, scale));
return longitudeDelta;
}
//
- (double)judgeLatition:(double)latitude {
if (latitude >= 90) {
latitude = 85.00;
}
if (latitude <= -90) {
latitude = -85.00;
}
return latitude;
}
//
- (double)judgeLongitude:(double)longitude {
if (longitude >= 180) {
longitude = 180.00;
}
if (longitude <= -180) {
longitude = -180.00;
}
return longitude;
}
- (FATExtLocationManager *)locationManager {
if (_locationManager == nil) {
_locationManager = [[FATExtLocationManager alloc] init];
_locationManager.delegate = self;
}
return _locationManager;
}
- (MKMapView *)mapView {
if (!_mapView) {
_mapView = [[MKMapView alloc] init];
_mapView.delegate = self;
_mapView.mapType = MKMapTypeStandard;
_mapView.showsUserLocation = YES;
_mapView.userTrackingMode = MKUserTrackingModeNone;
}
return _mapView;
}
@end

View File

@ -1,33 +0,0 @@
//
// FATOpenLocationViewController.h
// FinAppletExt
//
// Created by 耀 on 2021/12/9.
//
#import <UIKit/UIKit.h>
#import <FinApplet/FinApplet.h>
NS_ASSUME_NONNULL_BEGIN
typedef void (^SureBlock)(NSDictionary *locationInfo);
@interface FATOpenLocationViewController : FATUIViewController
@property (nonatomic, copy) dispatch_block_t cancelBlock;
@property (nonatomic, copy) SureBlock sureBlock;
///
@property (nonatomic, strong) NSString *latitude;
///
@property (nonatomic, strong) NSString *longitude;
@property (nonatomic, strong) NSString *scale;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *address;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,339 +0,0 @@
//
// FATOpenLocationViewController.m
// FinAppletExt
//
// Created by 耀 on 2021/12/9.
//
#import "FATOpenLocationViewController.h"
#import "FATExtHelper.h"
#import "MKMarkerView.h"
#import "FATExtLocationManager.h"
#import "FATWGS84ConvertToGCJ02.h"
#import "FATExtUtil.h"
#import <MapKit/MapKit.h>
@interface FATOpenLocationViewController () <MKMapViewDelegate, CLLocationManagerDelegate>
@property (nonatomic, strong) MKMapView *mapView;
@property (nonatomic, strong) UIButton *locationButton;
@property (nonatomic, strong) UIButton *returnButton;
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@property (nonatomic, assign) double Delta;
@end
@implementation FATOpenLocationViewController
- (MKMapView *)mapView {
if (!_mapView) {
_mapView = [[MKMapView alloc] init];
_mapView.delegate = self;
_mapView.mapType = MKMapTypeStandard;
_mapView.showsUserLocation = YES;
_mapView.userTrackingMode = MKUserTrackingModeNone;
}
return _mapView;
}
- (FATExtLocationManager *)locationManager {
if (_locationManager == nil) {
_locationManager = [[FATExtLocationManager alloc] init];
_locationManager.delegate = self;
}
return _locationManager;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self fatCreatUI];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 20, self.view.frame.size.height)];
view.backgroundColor = UIColor.clearColor;
[self.view addSubview:view];
UIScreenEdgePanGestureRecognizer *edgeGes = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgePan:)];
edgeGes.edges = UIRectEdgeLeft;
[view addGestureRecognizer:edgeGes];
}
- (void)dealloc {
// _mapView.showsUserLocation = NO;
// _mapView.userTrackingMode = MKUserTrackingModeNone;
[_mapView.layer removeAllAnimations];
[_mapView removeAnnotations:self.mapView.annotations];
[_mapView removeOverlays:self.mapView.overlays];
[_mapView removeFromSuperview];
_mapView.delegate = nil;
_mapView = nil;
}
- (void)edgePan:(UIPanGestureRecognizer *)recognizer {
[self dismissViewControllerAnimated:YES completion:^{
}];
}
- (void)fatCreatUI {
CGFloat width = self.view.bounds.size.width;
CGFloat height = self.view.bounds.size.height;
CGFloat bottomViewHeight = 100;
self.mapView.frame = CGRectMake(0, 0, width, height);
[self.view addSubview:self.mapView];
CGFloat top = [UIView fat_statusHeight];
self.returnButton = [[UIButton alloc] initWithFrame:CGRectMake(16, top, 50, 50)];
[self.returnButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_back_n"] forState:UIControlStateNormal];
[self.returnButton addTarget:self action:@selector(returnOnClick) forControlEvents:UIControlEventTouchUpInside];
[self.mapView addSubview:self.returnButton];
self.locationButton = [[UIButton alloc] initWithFrame:CGRectMake(width - 48 - 16.5, height - bottomViewHeight - 24.5 - 48, 48, 48)];
//
BOOL isDark = false;
if (@available(iOS 13.0, *)) {
isDark = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark);
}
if (isDark) {
[self.locationButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_dn"] forState:UIControlStateNormal];
[self.locationButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_dp"] forState:UIControlStateHighlighted];
} else {
[self.locationButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_ln"] forState:UIControlStateNormal];
[self.locationButton setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_location_lp"] forState:UIControlStateHighlighted];
}
[self.locationButton addTarget:self action:@selector(locationOnClick) forControlEvents:UIControlEventTouchUpInside];
[self.mapView addSubview:self.locationButton];
UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, height - bottomViewHeight, width, bottomViewHeight)];
if (@available(iOS 13.0, *)) {
bgView.backgroundColor = UIColor.systemGray6Color;
} else {
// Fallback on earlier versions
}
[self.mapView addSubview:bgView];
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 25.5, width - 70, 31)];
nameLabel.font = [UIFont systemFontOfSize:22];
nameLabel.text = self.name;
nameLabel.textColor = isDark ? [UIColor colorWithRed:208 / 255.0 green:208 / 255.0 blue:208 / 255.0 alpha:1 / 1.0] : [UIColor colorWithRed:34 / 255.0 green:34 / 255.0 blue:34 / 255.0 alpha:1 / 1.0];
[bgView addSubview:nameLabel];
UILabel *addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 65.5, width - 70, 16.5)];
addressLabel.font = [UIFont systemFontOfSize:12];
addressLabel.text = self.address;
addressLabel.textColor = UIColor.lightGrayColor;
[bgView addSubview:addressLabel];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(bgView.frame.size.width - 70, bottomViewHeight / 2 - 25, 50, 50)];
[button setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_navigation_n"] forState:UIControlStateNormal];
[button setImage:[FATExtHelper fat_ext_imageFromBundleWithName:@"map_navigation_p"] forState:UIControlStateHighlighted];
button.layer.cornerRadius = 25;
[button addTarget:self action:@selector(navigationOnClick) forControlEvents:UIControlEventTouchUpInside];
[bgView addSubview:button];
double delta = [self.scale doubleValue];
if (delta < 5) {
delta = 5.00;
}
if (delta > 18) {
delta = 18.00;
}
double LongitudeDelta = [self fat_getLongitudeDelta:delta];
self.Delta = LongitudeDelta;
CLLocationCoordinate2D centerCoord = {[self judgeLatition:[self.latitude doubleValue]], [self judgeLongitude:[self.longitude doubleValue]]};
[self.mapView setRegion:MKCoordinateRegionMake(centerCoord, MKCoordinateSpanMake(LongitudeDelta, LongitudeDelta)) animated:YES];
//
MKMarker *marker = [[MKMarker alloc] init];
marker.coordinate = centerCoord;
[self.mapView addAnnotation:marker];
}
- (void)locationOnClick {
[self startStandardUpdates];
}
- (void)returnOnClick {
[self dismissViewControllerAnimated:YES completion:^{
}];
}
- (void)startStandardUpdates {
if (![FATExtLocationManager locationServicesEnabled]) {
return;
}
CLAuthorizationStatus status = [FATExtLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
status == kCLAuthorizationStatusAuthorizedAlways ||
status == kCLAuthorizationStatusNotDetermined) {
//
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager startUpdatingLocation];
} else if (status == kCLAuthorizationStatusDenied) {
}
}
- (double)fat_getLongitudeDelta:(double)scale {
double longitudeDelta = (360 * self.mapView.frame.size.width / 256.0 / pow(2, scale));
return longitudeDelta;
}
- (void)navigationOnClick {
[self fat_openMapApp:@{@"latitude" : self.latitude, @"longitude" : self.longitude, @"destination" : self.name}];
}
/**
*
*
* @param manager
* @param locations
*/
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *location = [locations firstObject];
//
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:location.coordinate];
CLLocation *newLocations = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
[self.mapView setRegion:MKCoordinateRegionMake(newLocations.coordinate, MKCoordinateSpanMake(self.Delta, self.Delta)) animated:YES];
[self.locationManager stopUpdatingLocation];
}
- (nullable MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
// If the annotation is the user location, just return nil.Annotation,使
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
if ([annotation isKindOfClass:MKMarker.class]) {
MKMarker *marker = (MKMarker *)annotation;
MKAnnotationView *markerView = [mapView dequeueReusableAnnotationViewWithIdentifier:@"markerView"];
markerView.canShowCallout = YES;
markerView.annotation = marker;
markerView.image = marker.image;
return markerView;
}
return nil;
}
- (void)fat_openMapApp:(NSDictionary *)data {
/*
appurl Scheme
1.URL Scheme
2. baidumap
3. iosamap
4. comgooglemaps
IOS9plisturl scheme.
LSApplicationQueriesSchemes URL Scheme :
*/
// 1.app
NSString *appName = [FATExtUtil getAppName];
NSString *title = [NSString stringWithFormat:@"%@%@", [[FATClient sharedClient] fat_localizedStringForKey:@"Navigate to"], data[@"destination"]];
CLLocationCoordinate2D coordinate = {[data[@"latitude"] doubleValue], [data[@"longitude"] doubleValue]};
//
// 1.UIAlertController
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *appleAction = [UIAlertAction actionWithTitle:[[FATClient sharedClient] fat_localizedStringForKey:@"Apple Maps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
CLLocationCoordinate2D loc = CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude);
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:loc addressDictionary:nil]];
toLocation.name = data[@"destination"] ? data[@"destination"] : @"未知地点";
[MKMapItem openMapsWithItems:@[ currentLocation, toLocation ]
launchOptions:@{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsShowsTrafficKey : [NSNumber numberWithBool:YES]}];
}];
[appleAction setValue:[self labelColor] forKey:@"titleTextColor"];
UIAlertAction *bdAction = [UIAlertAction actionWithTitle:[[FATClient sharedClient] fat_localizedStringForKey:@"Baidu Maps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=目的地&mode=driving&coord_type=gcj02", coordinate.latitude, coordinate.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[bdAction setValue:[self labelColor] forKey:@"titleTextColor"];
UIAlertAction *gdAction = [UIAlertAction actionWithTitle:[[FATClient sharedClient] fat_localizedStringForKey:@"Amap"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
NSString *urlString = [[NSString stringWithFormat:@"iosamap://path?sourceApplication=%@&backScheme=%@&dlat=%f&dlon=%f&dev=0&t=0&dname=%@", appName, @"iosamap://", coordinate.latitude, coordinate.longitude, data[@"destination"]] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[gdAction setValue:[self labelColor] forKey:@"titleTextColor"];
UIAlertAction *googleAction = [UIAlertAction actionWithTitle:[[FATClient sharedClient] fat_localizedStringForKey:@"Google Maps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving", appName, @"comgooglemaps://", coordinate.latitude, coordinate.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[googleAction setValue:[self labelColor] forKey:@"titleTextColor"];
UIAlertAction *tencentAction = [UIAlertAction actionWithTitle:[[FATClient sharedClient] fat_localizedStringForKey:@"Tencent Maps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *_Nonnull action) {
NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=drive&to=%@&tocoord=%f,%f&coord_type=1&referer={ios.blackfish.XHY}",data[@"destination"],coordinate.latitude,coordinate.longitude] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}];
[tencentAction setValue:[self labelColor] forKey:@"titleTextColor"];
NSString *cancel = [[FATClient sharedClient] fat_localizedStringForKey:@"Cancel"];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction *_Nonnull action){
// [alertController ]
}];
[cancelAction setValue:[self labelColor] forKey:@"titleTextColor"];
// 1.app
[alertController addAction:appleAction];
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
[alertController addAction:bdAction];
}
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
[alertController addAction:gdAction];
}
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
[alertController addAction:googleAction];
}
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]){
[alertController addAction:tencentAction];
}
[alertController addAction:cancelAction];
UIViewController *topVC = [[UIApplication sharedApplication] fat_topViewController];
[topVC presentViewController:alertController animated:YES completion:nil];
}
- (UIColor *)labelColor {
if (@available(iOS 12.0, *)) {
BOOL isDark = (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark);
return isDark ? [UIColor colorWithRed:208/255.0 green:208/255.0 blue:208/255.0 alpha:1/1.0] : [UIColor colorWithRed:34/255.0 green:34/255.0 blue:34/255.0 alpha:1/1.0];
} else {
return [UIColor colorWithRed:34/255.0 green:34/255.0 blue:34/255.0 alpha:1/1.0];
}
}
//
- (double)judgeLatition:(double)latitude {
if (latitude >= 90) {
latitude = 85.00;
}
if (latitude <= -90) {
latitude = -85.00;
}
return latitude;
}
//
- (double)judgeLongitude:(double)longitude {
if (longitude >= 180) {
longitude = 180.00;
}
if (longitude <= -180) {
longitude = -180.00;
}
return longitude;
}
@end

View File

@ -1,66 +0,0 @@
//
// FATExtRecorder.h
// HLProject
//
// Created by Haley on 2021/12/28.
// Copyright © 2021 Haley. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>
typedef NS_ENUM(NSUInteger, FATFrameState) {
FATFrameStatePrepareToSend,
FATFrameStateAlreadyWillSend,
FATFrameStateAlreadySent
};
@class FATExtRecorder;
@protocol FATExtRecorderDelegate <NSObject>
- (void)extRecorder:(FATExtRecorder *)recorder
onFrameData:(NSData *)frameData
frameIndex:(NSInteger)frameIndex
isLastFrame:(BOOL)isLastFrame;
- (void)extRecorderDidCompletion:(FATExtRecorder *)recorder;
- (void)extRecorderBeginInterruption:(FATExtRecorder *)recorder;
- (void)extRecorderEndInterruption:(FATExtRecorder *)recorder withOptions:(NSUInteger)flags;
- (void)extRecorder:(FATExtRecorder *)recorder onError:(NSError *)error;
@end
@interface FATExtRecorder : NSObject
@property (nonatomic, assign) BOOL isStarted;
@property (nonatomic, assign) BOOL isRecording;
@property (nonatomic, assign) BOOL isPausing;
@property (nonatomic, strong) NSString *recordFilePath;
@property (nonatomic, weak) id<FATExtRecorderDelegate> delegate;
@property (nonatomic, readonly, copy) NSString *recorderId;
@property (nonatomic, strong) NSMutableArray *frameInfoArray;
@property (nonatomic, assign) FATFrameState frameState;
@property (nonatomic, assign) BOOL waitToSendBuffer;
@property (nonatomic, copy) void(^eventCallBack)(NSInteger eventType,NSString *eventName, NSDictionary *paramDic,NSDictionary *extDic);
- (BOOL)startRecordWithDict:(NSDictionary *)dict appId:(NSString *)appId;
- (BOOL)pauseRecord;
- (BOOL)resumeRecord;
- (BOOL)stopRecord;
@end

View File

@ -1,799 +0,0 @@
//
// FATExtRecorder.m
// HLProject
//
// Created by Haley on 2021/12/28.
// Copyright © 2021 Haley. All rights reserved.
//
#import "FATExtRecorder.h"
#import "FATExtUtil.h"
#import "lame.h"
#import <FinApplet/FinApplet.h>
#define FATDefaultBufferSize 4096 //4096,4096,4096
#define QUEUE_BUFFER_SIZE 3 //
@interface FATExtRecorder ()
{
AudioQueueRef audioQRef; //
AudioStreamBasicDescription inputDescription; //
AudioStreamBasicDescription outputDescription; //
AudioQueueBufferRef audioBuffers[QUEUE_BUFFER_SIZE]; //
AudioConverterRef _encodeConvertRef;
lame_t lame;
FILE *mp3;
int pcm_buffer_size;
uint8_t pcm_buffer[FATDefaultBufferSize*2];
}
@property (nonatomic, assign) AudioFileID recordFileID; //
@property (nonatomic, assign) SInt64 recordPacketNum;
@property (nonatomic, copy) NSString *recorderId;
//
@property (nonatomic, assign) UInt32 mChannelsPerFrame;
//
@property (nonatomic, assign) UInt32 mSampleRate;
//
@property (nonatomic, assign) UInt32 encodeBitRate;
//
@property (nonatomic, assign) int duration;
//
@property (nonatomic, copy) NSString *format;
@property (nonatomic, assign) long long frameSize;
@property (nonatomic, assign) BOOL shouldFrameCallback;
@property (nonatomic, assign) NSInteger currentBufferIndex;
// buffer
@property (nonatomic, strong) NSMutableData *currentFrameData;
@property (nonatomic, assign) long long currentFrameOffset;
@end
@implementation FATExtRecorder
void FATAudioInputCallbackHandler(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription *inPacketDesc) {
FATExtRecorder *recorder = (__bridge FATExtRecorder *)(inUserData);
[recorder processAudioBuffer:inBuffer inStartTime:inStartTime inNumPackets:inNumPackets inPacketDesc:inPacketDesc audioQueue:inAQ];
}
OSStatus FATAudioConverterComplexInputDataProc(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) {
FATExtRecorder *recorder = (__bridge FATExtRecorder *)(inUserData);
BOOL result = [recorder handleConverterDataProcWithBufferList:ioData];
if (result) {
return noErr;
}
return -1;
}
#pragma mark - override
- (instancetype)init {
self = [super init];
if (self) {
[self p_addNotifications];
}
return self;
}
- (void)dealloc {
// NSLog(@"FATExtRecorder---dealloc");
[[NSNotificationCenter defaultCenter] removeObserver:self];
AudioQueueDispose(audioQRef, true);
}
- (void)handleInterruption:(NSNotification *)notification {
NSDictionary *info = notification.userInfo;
AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
if (type == AVAudioSessionInterruptionTypeBegan) {
if ([self.delegate respondsToSelector:@selector(extRecorderBeginInterruption:)]) {
[self.delegate extRecorderBeginInterruption:self];
}
} else {
AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
if (options == AVAudioSessionInterruptionOptionShouldResume) {
//Handle Resume
}
if ([self.delegate respondsToSelector:@selector(extRecorderEndInterruption:withOptions:)]) {
[self.delegate extRecorderEndInterruption:self withOptions:options];
}
}
}
- (BOOL)startRecordWithDict:(NSDictionary *)dict appId:(NSString *)appId {
self.currentBufferIndex = 0;
self.currentFrameOffset = 0;
self.currentFrameData = [[NSMutableData alloc] init];
self.frameState = FATFrameStatePrepareToSend;
self.frameInfoArray = [NSMutableArray array];
memset(pcm_buffer, 0, pcm_buffer_size);
pcm_buffer_size = 0;
self.recorderId = appId;
// 1.
//
NSString *audioSource;
if (!audioSource || ![audioSource isKindOfClass:[NSString class]]) {
audioSource = @"auto";
} else {
audioSource = dict[@"audioSource"];
}
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
if ([audioSource isEqualToString:@"buildInMic"]) {
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:NULL];
} else if ([audioSource isEqualToString:@"headsetMic"]) {
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:NULL];
} else {
if (@available(iOS 10.0, *)) {
// 4545
// NSUInteger options = AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionAllowAirPlay;
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:AVAudioSessionModeDefault options:45 error:NULL];
} else {
NSUInteger options = AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionAllowBluetooth;
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:options error:NULL];
}
}
[audioSession setActive:YES error:NULL];
// 1.1
NSString *format = [self _format:dict];
self.format = format;
AudioFormatID formatID = [self _formatIDWithFormat:format];
inputDescription.mFormatID = formatID;
// 1.2.
NSString *numberOfChannelsString = dict[@"numberOfChannels"];
if (![self _isValidWithNumberOfChannelsString:numberOfChannelsString]) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
NSError *error = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"operateRecorder:fail channel error"}];
[self.delegate extRecorder:self onError:error];
}
return NO;
}
NSNumber *numberOfChannelsNub = [NSNumber numberWithInt:[numberOfChannelsString intValue]];
if (numberOfChannelsString == nil) {
numberOfChannelsNub = @(2);
}
if ([format isEqualToString:@"aac"]) {
// aac
numberOfChannelsNub = @(1);
}
inputDescription.mChannelsPerFrame = [numberOfChannelsNub intValue];
self.mChannelsPerFrame = [numberOfChannelsNub intValue];
// 1.3.
NSString *sampleRateString = dict[@"sampleRate"];
NSNumber *sampleRateNub;
if (sampleRateString == nil || ![sampleRateString isKindOfClass:[NSString class]]) {
sampleRateNub = @(8000);
} else {
sampleRateNub = [NSNumber numberWithInt:[sampleRateString intValue]];
}
inputDescription.mSampleRate = [sampleRateNub floatValue];
self.mSampleRate = inputDescription.mSampleRate;
// 1.4.
NSString *encodeBitRateString = dict[@"encodeBitRate"];
NSNumber *encodeBitRateNub;
if (encodeBitRateString == nil || ![encodeBitRateString isKindOfClass:[NSString class]]) {
encodeBitRateNub = @(48000);
} else {
encodeBitRateNub = [NSNumber numberWithInt:[encodeBitRateString intValue]];
}
self.encodeBitRate = [encodeBitRateNub floatValue];
NSString *durationString = dict[@"duration"];
NSNumber *durationNub;
if (durationString == nil || ![durationString isKindOfClass:[NSString class]]) {
durationNub = @(60000);
} else {
durationNub = [NSNumber numberWithInt:[durationString intValue]];
}
if ([durationNub intValue] <= 0) {
durationNub = @(60000);
}
if ([durationNub intValue] > 600000) {
durationNub = @(600000);
}
self.duration = [durationNub intValue];
//
inputDescription.mFormatID = kAudioFormatLinearPCM;
inputDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
inputDescription.mBitsPerChannel = 16;
//
inputDescription.mBytesPerFrame = (inputDescription.mBitsPerChannel / 8) * inputDescription.mChannelsPerFrame;
//
inputDescription.mBytesPerPacket = inputDescription.mBytesPerFrame;
//
inputDescription.mFramesPerPacket = 1;
// 2.
NSString *fileName = [self _fileNameWithFormat:format];
NSString *filePath = [[FATExtUtil tmpDirWithAppletId:appId] stringByAppendingPathComponent:fileName];
self.recordFilePath = filePath;
if ([format isEqualToString:@"mp3"]) {
mp3 = fopen([self.recordFilePath cStringUsingEncoding:1], "wb");
lame = lame_init();
//
lame_set_in_samplerate(lame, inputDescription.mSampleRate);
//
lame_set_num_channels(lame, inputDescription.mChannelsPerFrame);
lame_set_VBR(lame, vbr_default);
lame_init_params(lame);
} else if ([format isEqualToString:@"aac"]) {
NSError *error;
if (![self _createConverter:&error]) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
[self.delegate extRecorder:self onError:error];
}
return NO;
}
[self copyEncoderCookieToFile];
}
OSStatus status = AudioQueueNewInput(&inputDescription, FATAudioInputCallbackHandler, (__bridge void *)(self), NULL, NULL, 0, &audioQRef);
if ( status != kAudioSessionNoError ) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
NSError *error = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"AudioQueueNewInput fail"}];
[self.delegate extRecorder:self onError:error];
}
return NO;
}
// 1.5 frameSize
NSString *frameSizeString = dict[@"frameSize"];
if (![frameSizeString isKindOfClass:[NSString class]]) {
frameSizeString = nil;
}
//inbuffercallBackframeSize
long long bufferByteSize = FATDefaultBufferSize;
if ([frameSizeString floatValue]> 0.00 && [self _canCallbackFormat:format]) {
self.shouldFrameCallback = YES;
self.frameSize = (long long)[frameSizeString floatValue] * 1024;
}
if ([format isEqualToString:@"aac"]) {
// aac10242
bufferByteSize = 1024 * 2 * self.mChannelsPerFrame;
}
for (int i = 0; i < QUEUE_BUFFER_SIZE; i++){
AudioQueueAllocateBuffer(audioQRef, bufferByteSize, &audioBuffers[i]);
AudioQueueEnqueueBuffer(audioQRef, audioBuffers[i], 0, NULL);
}
CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, (CFStringRef)self.recordFilePath, NULL);
//
if ([format isEqualToString:@"aac"]) {
AudioFileCreateWithURL(url, kAudioFileCAFType, &outputDescription, kAudioFileFlags_EraseFile, &_recordFileID);
} else {
AudioFileCreateWithURL(url, kAudioFileCAFType, &inputDescription, kAudioFileFlags_EraseFile, &_recordFileID);
}
CFRelease(url);
self.recordPacketNum = 0;
status = AudioQueueStart(audioQRef, NULL);
if (status != kAudioSessionNoError) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
NSError *error = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"AudioQueueStart fail"}];
[self.delegate extRecorder:self onError:error];
}
AudioQueueStop(audioQRef, NULL);
return NO;
}
self.isStarted = YES;
self.isRecording = YES;
return YES;
}
- (BOOL)pauseRecord {
OSStatus status = AudioQueuePause(audioQRef);
if (status != kAudioSessionNoError) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
NSError *error = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"pause fail"}];
[self.delegate extRecorder:self onError:error];
}
return NO;
}
self.isRecording = NO;
self.isPausing = YES;
return YES;
}
- (BOOL)resumeRecord {
OSStatus status = AudioQueueStart(audioQRef, NULL);
if (status != kAudioSessionNoError) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onError:)]) {
NSError *error = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"resume fail"}];
[self.delegate extRecorder:self onError:error];
}
return NO;
}
self.isRecording = YES;
self.isPausing = NO;
return YES;
}
- (BOOL)stopRecord {
if (self.isRecording) {
self.isRecording = NO;
}
self.isStarted = NO;
//
AudioQueueStop(audioQRef, true);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
AudioFileClose(_recordFileID);
[self didEndRecord];
});
return YES;
}
#pragma mark - private
- (void)processAudioBuffer:(AudioQueueBufferRef)inBuffer inStartTime:(AudioTimeStamp *)inStartTime inNumPackets:(UInt32)inNumPackets inPacketDesc:(AudioStreamPacketDescription *)inPacketDesc audioQueue:(AudioQueueRef)audioQueueRef
{
const int audioSize = inBuffer->mAudioDataByteSize;
// NSLog(@"processAudioBuffer---inNumPackets:%d, size:%d", inNumPackets, audioSize);
if (inNumPackets > 0) {
if ([self.format isEqualToString:@"mp3"]) {
unsigned char mp3_buffer[audioSize];
// 1char *charshort *short2
// 2packet 1 ; 2 Bytes; 4 Bytes
// nsamples = inBuffer->mAudioDataByteSize / 2;
// nsamples = inBuffer->mAudioDataByteSize / 4;
// nsamples inNumPackets;
int nsamples = inNumPackets;
/**
使lame_encode_buffer_interleaved
lame_encode_buffer //16
lame_encode_buffer_interleaved //
lame_encode_buffer_float //32
*/
int recvLen;
if (self.mChannelsPerFrame == 1) {
//
recvLen = lame_encode_buffer(lame, inBuffer->mAudioData, NULL, nsamples, mp3_buffer, audioSize);
} else {
recvLen = lame_encode_buffer_interleaved(lame, inBuffer->mAudioData, nsamples, mp3_buffer, audioSize);
}
//
fwrite(mp3_buffer, recvLen, 1, mp3);
if (self.shouldFrameCallback) {
[self.currentFrameData appendBytes:mp3_buffer length:recvLen];
}
// NSLog(@"%d", recvLen);
} else if ([self.format isEqualToString:@"pcm"]) {
// MP3
void *bufferData = inBuffer->mAudioData;
UInt32 buffersize = inBuffer->mAudioDataByteSize;
if (self.shouldFrameCallback) {
[self.currentFrameData appendBytes:bufferData length:buffersize];
}
AudioFileWritePackets(self.recordFileID, FALSE, audioSize, inPacketDesc, self.recordPacketNum, &inNumPackets, inBuffer->mAudioData);
self.recordPacketNum += inNumPackets;
} else if ([self.format isEqualToString:@"aac"]) {
memcpy(pcm_buffer + pcm_buffer_size, inBuffer->mAudioData, inBuffer->mAudioDataByteSize);
pcm_buffer_size = pcm_buffer_size + inBuffer->mAudioDataByteSize;
long long willEncodePCMBufferSize = 1024 * 2 * self.mChannelsPerFrame;
if (pcm_buffer_size >= willEncodePCMBufferSize) {
AudioBufferList *bufferList = [self convertedAACBufferListWith:inBuffer];
memcpy(pcm_buffer, pcm_buffer + willEncodePCMBufferSize, pcm_buffer_size - willEncodePCMBufferSize);
pcm_buffer_size = pcm_buffer_size - willEncodePCMBufferSize;
void *bufferData = inBuffer->mAudioData;
UInt32 buffersize = inBuffer->mAudioDataByteSize;
if (self.shouldFrameCallback) {
[self.currentFrameData appendBytes:bufferData length:buffersize];
}
// free memory
if (bufferList) {
free(bufferList->mBuffers[0].mData);
free(bufferList);
}
}
} else if ([self.format isEqualToString:@"wav"]) {
// wav
void *bufferData = inBuffer->mAudioData;
UInt32 buffersize = inBuffer->mAudioDataByteSize;
AudioFileWritePackets(self.recordFileID, FALSE, audioSize, inPacketDesc, self.recordPacketNum, &inNumPackets, inBuffer->mAudioData);
self.recordPacketNum += inNumPackets;
}
if (self.shouldFrameCallback) {
if ([self.format isEqualToString:@"pcm"]) {
long long fileSize = [self _getFileSize:self.recordFilePath];
long long currentFrameSize;
if (self.currentBufferIndex == 0) {
currentFrameSize = fileSize - FATDefaultBufferSize;
self.currentFrameOffset = FATDefaultBufferSize;
} else {
currentFrameSize = fileSize - self.currentFrameOffset;
}
if (fileSize > self.frameSize) {
if ([self.delegate respondsToSelector:@selector(extRecorder:onFrameData:frameIndex:isLastFrame:)]) {
[self.delegate extRecorder:self onFrameData:self.currentFrameData frameIndex:self.currentBufferIndex isLastFrame:NO];
}
self.currentFrameData = [[NSMutableData alloc] init];
self.currentBufferIndex++;
}
} else if ([self.format isEqualToString:@"mp3"]) {
long long fileSize = [self _getFileSize:self.recordFilePath];
long long currentFrameSize;
if (self.currentBufferIndex == 0) {
currentFrameSize = fileSize - FATDefaultBufferSize;
self.currentFrameOffset = FATDefaultBufferSize;
} else {
currentFrameSize = fileSize - self.currentFrameOffset;
}
if (currentFrameSize > self.frameSize) {
//
NSString *frameFilePath = [self.recordFilePath stringByDeletingPathExtension];
frameFilePath = [frameFilePath stringByAppendingFormat:@"_%d", self.currentBufferIndex];
frameFilePath = [frameFilePath stringByAppendingPathExtension:self.recordFilePath.pathExtension];
BOOL result = [self.currentFrameData writeToFile:frameFilePath atomically:YES];
// NSLog(@"写入文件:%@, 结果:%d",frameFilePath.lastPathComponent, result);
if ([self.delegate respondsToSelector:@selector(extRecorder:onFrameData:frameIndex:isLastFrame:)]) {
[self.delegate extRecorder:self onFrameData:self.currentFrameData frameIndex:self.currentBufferIndex isLastFrame:NO];
}
self.currentFrameData = [[NSMutableData alloc] init];
self.currentFrameOffset += currentFrameSize;
self.currentBufferIndex++;
}
} else if ([self.format isEqualToString:@"aac"]) {
long long fileSize = [self _getFileSize:self.recordFilePath];
// NSLog(@"fileSize:%lld", fileSize);
long long currentFrameSize;
if (self.currentBufferIndex == 0) {
currentFrameSize = fileSize - FATDefaultBufferSize;
self.currentFrameOffset = FATDefaultBufferSize;
} else {
currentFrameSize = fileSize - self.currentFrameOffset;
}
if (currentFrameSize > self.frameSize) {
//
// NSLog(@"currentFrameSize:%d", currentFrameSize);
NSString *frameFilePath = [self.recordFilePath stringByDeletingPathExtension];
frameFilePath = [frameFilePath stringByAppendingFormat:@"_%d", self.currentBufferIndex];
frameFilePath = [frameFilePath stringByAppendingPathExtension:self.recordFilePath.pathExtension];
BOOL result = [self.currentFrameData writeToFile:frameFilePath atomically:YES];
// NSLog(@"写入文件:%@, 结果:%d",frameFilePath.lastPathComponent, result);
if ([self.delegate respondsToSelector:@selector(extRecorder:onFrameData:frameIndex:isLastFrame:)]) {
[self.delegate extRecorder:self onFrameData:self.currentFrameData frameIndex:self.currentBufferIndex isLastFrame:NO];
}
self.currentFrameData = [[NSMutableData alloc] init];
self.currentFrameOffset += currentFrameSize;
self.currentBufferIndex++;
}
}
}
}
NSTimeInterval recordDuration = inStartTime->mSampleTime / self.mSampleRate * 1000.0;
if (recordDuration >= self.duration) {
if (self.isRecording) {
[self stopRecord];
}
return;
}
if (self.isRecording || self.isPausing) {
// 便使
AudioQueueEnqueueBuffer(audioQueueRef, inBuffer, 0, NULL);
}
}
- (BOOL)handleConverterDataProcWithBufferList:(AudioBufferList *)bufferList
{
if ([self.format isEqualToString:@"aac"]) {
bufferList->mBuffers[0].mData = pcm_buffer;
bufferList->mBuffers[0].mNumberChannels = self.mChannelsPerFrame;
bufferList->mBuffers[0].mDataByteSize = 1024 * 2 * self.mChannelsPerFrame;
return YES;
}
return NO;
}
- (void)didEndRecord {
if ([self.format isEqualToString:@"mp3"]) {
// VBR ,
lame_mp3_tags_fid(lame, mp3);
lame_close(lame);
fclose(mp3);
}
if (self.currentFrameData.length > 0) {
NSString *frameFilePath = [self.recordFilePath stringByDeletingPathExtension];
frameFilePath = [frameFilePath stringByAppendingFormat:@"_%d", self.currentBufferIndex];
frameFilePath = [frameFilePath stringByAppendingPathExtension:self.recordFilePath.pathExtension];
BOOL result = [self.currentFrameData writeToFile:frameFilePath atomically:YES];
// NSLog(@"Last写入文件:%@, 结果:%d",frameFilePath.lastPathComponent, result);
if ([self.delegate respondsToSelector:@selector(extRecorder:onFrameData:frameIndex:isLastFrame:)]) {
[self.delegate extRecorder:self onFrameData:self.currentFrameData frameIndex:self.currentBufferIndex isLastFrame:YES];
}
self.currentFrameData = nil;
self.currentFrameOffset = 0;
self.currentBufferIndex = 0;
}
if ([self.delegate respondsToSelector:@selector(extRecorderDidCompletion:)]) {
[self.delegate extRecorderDidCompletion:self];
}
// ()
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:YES state:FATCapsuleButtonStateMicroPhone animate:NO];
}
}
- (void)p_addNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:nil];
}
#pragma mark - tool method
- (NSString *)_format:(NSDictionary *)data {
NSString *format = data[@"format"];
if (!format || ![format isKindOfClass:[NSString class]]) {
format = @"aac";
}
format = [format lowercaseString];
NSArray *validFormats = @[@"mp3", @"aac", @"wav", @"pcm"];
if (![validFormats containsObject:format]) {
return @"aac";
}
return format;
}
- (AudioFormatID)_formatIDWithFormat:(NSString *)format {
return kAudioFormatLinearPCM;
}
- (BOOL)_isValidWithNumberOfChannelsString:(NSString *)numberOfChannelsString {
if (!numberOfChannelsString) {
return YES;
}
if (![numberOfChannelsString isKindOfClass:[NSString class]]) {
return NO;
}
if ([numberOfChannelsString isEqualToString:@"1"] || [numberOfChannelsString isEqualToString:@"2"]) {
return YES;
}
return NO;
}
- (NSString *)_fileNameWithFormat:(NSString *)format {
NSString *currentDt = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]];
NSData *data = [currentDt dataUsingEncoding:NSUTF8StringEncoding];
NSString *nameMD5 = [[FATExtUtil fat_md5WithBytes:(char *)[data bytes] length:data.length] lowercaseString];
NSString *extensionName = [self _extensionNameWithFormat:format];
NSString *fileName = [NSString stringWithFormat:@"tmp_%@%@", nameMD5, extensionName];
return fileName;
}
- (NSString *)_extensionNameWithFormat:(NSString *)format {
// if ([format isEqualToString:@"aac"]) {
// return @".m4a";
// }
if ([format isEqualToString:@"pcm"]) {
return @".caf";
}
NSString *ext = [NSString stringWithFormat:@".%@", format];
return ext;
}
- (BOOL)_canCallbackFormat:(NSString *)format
{
if ([format isEqualToString:@"mp3"]) {
return YES;
}
if ([format isEqualToString:@"pcm"]) {
return YES;
}
if ([format isEqualToString:@"aac"]) {
return YES;
}
return NO;
}
- (long long)_getFileSize:(NSString *)path
{
NSFileManager *filemanager = [NSFileManager defaultManager];
if (![filemanager fileExistsAtPath:path]) {
return 0;
}
NSDictionary *attributes = [filemanager attributesOfItemAtPath:path error:nil];
NSNumber *theFileSize = [attributes objectForKey:NSFileSize];
return [theFileSize longLongValue];
}
- (BOOL)_createConverter:(NSError **)aError {
// encodeConverterComplexInputDataProc
AudioStreamBasicDescription sourceDes = inputDescription; //
AudioStreamBasicDescription targetDes; //
//
memset(&targetDes, 0, sizeof(targetDes));
targetDes.mFormatID = kAudioFormatMPEG4AAC;
targetDes.mSampleRate = inputDescription.mSampleRate ;
targetDes.mChannelsPerFrame = inputDescription.mChannelsPerFrame;
targetDes.mFramesPerPacket = 1024; // AACtargetDes.mFramesPerPacket1024AAC1024inNumPackets
OSStatus status = 0;
UInt32 targetSize = sizeof(targetDes);
status = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &targetSize, &targetDes);
memset(&outputDescription, 0, sizeof(outputDescription));
memcpy(&outputDescription, &targetDes, targetSize);
//
AudioClassDescription audioClassDes;
status = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders,
sizeof(targetDes.mFormatID),
&targetDes.mFormatID,
&targetSize);
UInt32 numEncoders = targetSize/sizeof(AudioClassDescription);
AudioClassDescription audioClassArr[numEncoders];
AudioFormatGetProperty(kAudioFormatProperty_Encoders,
sizeof(targetDes.mFormatID),
&targetDes.mFormatID,
&targetSize,
audioClassArr);
for (int i = 0; i < numEncoders; i++) {
if (audioClassArr[i].mSubType == kAudioFormatMPEG4AAC && audioClassArr[i].mManufacturer == kAppleSoftwareAudioCodecManufacturer) {
memcpy(&audioClassDes, &audioClassArr[i], sizeof(AudioClassDescription));
break;
}
}
status = AudioConverterNewSpecific(&sourceDes, &targetDes, 1, &audioClassDes, &_encodeConvertRef);
if (status != noErr) {
*aError = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"create converter fail"}];
// NSLog(@"Error : New convertRef failed");
return NO;
}
targetSize = sizeof(sourceDes);
status = AudioConverterGetProperty(_encodeConvertRef, kAudioConverterCurrentInputStreamDescription, &targetSize, &sourceDes);
targetSize = sizeof(targetDes);
status = AudioConverterGetProperty(_encodeConvertRef, kAudioConverterCurrentOutputStreamDescription, &targetSize, &targetDes);
//
UInt32 bitRate = self.encodeBitRate;
targetSize = sizeof(bitRate);
status = AudioConverterSetProperty(_encodeConvertRef,
kAudioConverterEncodeBitRate,
targetSize, &bitRate);
if (status != noErr) {
*aError = [NSError errorWithDomain:@"FATExtRecorder" code:-1 userInfo:@{NSLocalizedDescriptionKey:@"encodeBitRate not applicable"}];
// NSLog(@"Error : set encodeBitRate failed");
return NO;
}
return YES;
}
- (void)copyEncoderCookieToFile {
UInt32 cookieSize = 0;
OSStatus status = AudioConverterGetPropertyInfo(_encodeConvertRef, kAudioConverterCompressionMagicCookie, &cookieSize, NULL);
if (status != noErr || cookieSize == 0) {
return;
}
char *cookie = (char *)malloc(cookieSize * sizeof(char));
status = AudioConverterGetProperty(_encodeConvertRef, kAudioConverterCompressionMagicCookie, &cookieSize, cookie);
if (status == noErr) {
status = AudioFileSetProperty(_recordFileID, kAudioFilePropertyMagicCookieData, cookieSize, cookie);
if (status == noErr) {
UInt32 willEatTheCookie = false;
status = AudioFileGetPropertyInfo(_recordFileID, kAudioFilePropertyMagicCookieData, NULL, &willEatTheCookie);
printf("Writing magic cookie to destination file: %u\n cookie:%d \n", (unsigned int)cookieSize, willEatTheCookie);
} else {
printf("Even though some formats have cookies, some files don't take them and that's OK\n");
}
} else {
printf("Could not Get kAudioConverterCompressionMagicCookie from Audio Converter!\n");
}
free(cookie);
}
- (AudioBufferList *)convertedAACBufferListWith:(AudioQueueBufferRef)inBuffer
{
UInt32 maxPacketSize = 0;
UInt32 size = sizeof(maxPacketSize);
OSStatus status;
status = AudioConverterGetProperty(_encodeConvertRef,
kAudioConverterPropertyMaximumOutputPacketSize,
&size,
&maxPacketSize);
AudioBufferList *bufferList = (AudioBufferList *)malloc(sizeof(AudioBufferList));
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mNumberChannels = self.mChannelsPerFrame;
bufferList->mBuffers[0].mData = malloc(maxPacketSize);
bufferList->mBuffers[0].mDataByteSize = 1024 * 2 * self.mChannelsPerFrame;
UInt32 inNumPackets = 1;
AudioStreamPacketDescription outputPacketDescriptions;
status = AudioConverterFillComplexBuffer(_encodeConvertRef,
FATAudioConverterComplexInputDataProc,
(__bridge void * _Nullable)(self),
&inNumPackets,
bufferList,
&outputPacketDescriptions);
if (status != noErr) {
free(bufferList->mBuffers[0].mData);
free(bufferList);
return nil;
}
status = AudioFileWritePackets(self.recordFileID,
FALSE,
bufferList->mBuffers[0].mDataByteSize,
&outputPacketDescriptions,
self.recordPacketNum,
&inNumPackets,
bufferList->mBuffers[0].mData);
if (status == noErr) {
self.recordPacketNum += inNumPackets; //
} else {
// NSLog(@"数据写入失败");
}
return bufferList;
}
@end

View File

@ -1,105 +0,0 @@
//
// FATExtBaseApi.h
// FinAppletExtension
//
// Created by Haley on 2020/8/11.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>
@class FATAppletInfo;
@protocol FATApiHanderContextDelegate <NSObject>
//
- (UIViewController *)getCurrentViewController;
//id
- (NSString *)getCurrentPageId;
/// APIservicepage
/// eventName
/// eventType 0: service(callSubscribeHandlerWithEvent) 1:page(callSubscribeHandlerWithEvent) int便
/// paramDic
/// extDic 便 webId servicejsContextKeyjsContextValueserviceJSContext
- (void)sendResultEvent:(NSInteger)eventType eventName:(NSString *)eventName eventParams:(NSDictionary *)param extParams:(NSDictionary *)extDic;
@optional
- (NSString *)insertChildView:(UIView *)childView viewId:(NSString *)viewId parentViewId:(NSString *)parentViewId isFixed:(BOOL)isFixed isHidden:(BOOL)isHidden;
//hideNO使
/// @param childView
/// @param viewId id
/// @param parentViewId idWkScrollViewidcid
/// @param isFixed NOYESNOYES
- (void)updateChildViewHideProperty:(UIView *)childView viewId:(NSString *)viewId parentViewId:(NSString *)parentViewId isFixed:(BOOL)isFixed isHidden:(BOOL)isHidden complete:(void(^)(BOOL result))complete;
- (UIView *)getChildViewById:(NSString *)viewId;
- (BOOL)removeChildView:(NSString *)viewId;
@end
@protocol FATApiProtocol <NSObject>
@required
@property (nonatomic, strong) FATAppletInfo *appletInfo;
/**
api
*/
@property (nonatomic, readonly, copy) NSString *command;
/**
*/
@property (nonatomic, readonly, copy) NSDictionary<NSString *, id> *param;
@property (nonatomic, weak) id<FATApiHanderContextDelegate> context;
/**
API,
@param success
@param failure
@param cancel
*/
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel;
@optional
/**
api
*/
- (NSString *)setupSyncApi;
@end
@interface FATExtBaseApi : NSObject<FATApiProtocol>
@property (nonatomic, copy, readonly) NSDictionary *param;
@property (nonatomic, strong) FATAppletInfo *appletInfo;
/**
api
*/
@property (nonatomic, readonly, copy) NSString *command;
@property (nonatomic, weak) id<FATApiHanderContextDelegate> context;
//+ (FATExtBaseApi *)apiWithCommand:(NSString *)command param:(NSDictionary *)param;
//- (void)setupApiWithCallback:(FATExtensionApiCallback)callback;
//APIsdkAPIAPI使sdkAPI
+ (id<FATApiProtocol>)fat_apiWithApiClass:(NSString *)apiClassName params:(NSDictionary *)params;
@end

View File

@ -1,180 +0,0 @@
//
// FATExtBaseApi.m
// FinAppletExtension
//
// Created by Haley on 2020/8/11.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtBaseApi.h"
#import <objc/runtime.h>
@implementation FATExtBaseApi
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
//
if (cancel) {
cancel(nil);
}
if (success) {
success(@{});
}
if (failure) {
failure(nil);
}
}
/**
api
*/
- (NSString *)setupSyncApi {
return nil;
}
+ (id<FATApiProtocol>)fat_apiWithApiClass:(NSString *)apiClassName params:(NSDictionary *)params {
if (!apiClassName) {
return nil;
}
Class apiClass = NSClassFromString(apiClassName);
if (!apiClass) {
return nil;
}
id apiObj = [[apiClass alloc]init];
if (![apiObj conformsToProtocol:@protocol(FATApiProtocol)]) {
return nil;
}
id<FATApiProtocol> api = (id<FATApiProtocol>)apiObj;
NSString *apiName = @"";
//
NSArray *apiNameArray = [apiClassName componentsSeparatedByString:@"_"];
if (apiNameArray && apiNameArray.count > 1) {
apiName = apiNameArray[1];
}
[self setAPiObjectProperty:api command:apiName params:params];
return api;
}
+ (void)setAPiObjectProperty:(id<FATApiProtocol>) api command:(NSString *)command params:(NSDictionary *)param {
if (![api isKindOfClass:NSObject.class]) {
return;
}
NSObject *apiObj = (NSObject *)api;
[apiObj setValue:command forKey:@"command"];
[apiObj setValue:param forKey:@"param"];
//postMessageparamsNSString
if ([param isKindOfClass:NSDictionary.class]) {
for (NSString *datakey in param.allKeys) {
NSString *propertyKey = datakey;
@autoreleasepool {
objc_property_t property = class_getProperty([apiObj class], [propertyKey UTF8String]);
if (!property) {
continue;
}
id value = [param objectForKey:datakey];
id safetyValue = [self parseFromKeyValue:value];
if (!safetyValue) continue;
NSString *propertyType = [NSString stringWithUTF8String:property_copyAttributeValue(property, "T")];
propertyType = [propertyType stringByReplacingOccurrencesOfString:@"@" withString:@""];
propertyType = [propertyType stringByReplacingOccurrencesOfString:@"\\" withString:@""];
propertyType = [propertyType stringByReplacingOccurrencesOfString:@"\"" withString:@""];
//NSLog(@"propertyType:%@,value是%@", propertyType,value);
//
if (
[propertyType isEqualToString:@"NSString"] ||
[propertyType isEqualToString:@"NSArray"] ||
[propertyType isEqualToString:@"NSDictionary"]) {
if (![safetyValue isKindOfClass:NSClassFromString(propertyType)]) {
continue;
}
}
//NSNumberstring
//
[apiObj setValue:safetyValue forKey:propertyKey];
}
}
}
}
//+ (id)parseFromKeyValue:(id)value {
// //
// if ([value isKindOfClass:[NSNull class]]) {
// return nil;
// }
//
// if ([value isKindOfClass:[NSNumber class]]) { //
// value = [NSString stringWithFormat:@"%@", value];
// }
//
// return value;
//}
//// -
+ (id)parseFromKeyValue:(id)value {
//
if ([value isKindOfClass:[NSNull class]]) {
return nil;
}
if ([value isKindOfClass:[NSNumber class]]) { //
value = [NSString stringWithFormat:@"%@", value];
} else if ([value isKindOfClass:[NSArray class]]) { //
value = [self parseFromArray:value];
} else if ([value isKindOfClass:[NSDictionary class]]) { //
value = [self parseFromDictionary:value];
}
return value;
}
// -
+ (NSDictionary *)parseFromDictionary:(NSDictionary *)container {
if ([container isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *result = [NSMutableDictionary new];
for (id key in container.allKeys) {
@autoreleasepool {
id value = container[key];
id safetyValue = [self parseFromKeyValue:value];
if (!safetyValue) {
safetyValue = @"";
}
[result setObject:safetyValue forKey:key];
}
}
return result;
}
return container;
}
// -
+ (NSArray *)parseFromArray:(NSArray *)container {
if ([container isKindOfClass:[NSArray class]]) {
NSMutableArray *result = [NSMutableArray new];
for (int i = 0; i < container.count; i++) {
@autoreleasepool {
id value = container[i];
id safetyValue = [self parseFromKeyValue:value];
if (!safetyValue) {
safetyValue = @"";
}
[result addObject:safetyValue];
}
}
return result;
}
return container;
}
@end

View File

@ -1,27 +0,0 @@
//
// FATExt_recorderManager.h
// FinAppletExt
//
// Created by Haley on 2021/1/21.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import "FATExtBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_recorderManager : FATExtBaseApi
/**
*/
@property (nonatomic, copy) NSString *method;
/**
*/
@property (nonatomic, copy) NSDictionary *data;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,87 +0,0 @@
//
// FATExt_recorderManager.m
// FinAppletExt
//
// Created by Haley on 2021/1/21.
// Copyright © 2021 finogeeks. All rights reserved.
//
#import "FATExt_recorderManager.h"
#import "FATExtRecordManager.h"
#import "FATClient+ext.h"
#import "FATExtUtil.h"
@implementation FATExt_recorderManager
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
NSArray *validMethods = @[@"start",@"pause",@"resume",@"stop",@"onFrameRecordedRemove"];
NSString *method = self.method;
if (![validMethods containsObject:method]) {
return;
}
__block NSDictionary *dataDict = self.data;
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
BOOL result = [[FATExtRecordManager shareManager] checkRecordWithMethod:method data:dataDict appletId:appInfo.appId];
if (!result) {
return;
}
if ([method isEqualToString:@"start"]) {
[[FATClient sharedClient] fat_requestAppletAuthorize:FATAuthorizationTypeMicrophone appletId:appInfo.appId complete:^(NSInteger status) {
if (status == 1) { //
if (failure) {
failure(@{@"errMsg" : @"unauthorized,用户未授予麦克风权限"});
}
NSDictionary *params = @{
@"method" : @"onError",
@"data" : @{@"errMsg" : @"operateRecorder:fail fail_system permissionn denied"},
};
if (self.context) {
[self.context sendResultEvent:0 eventName:@"onRecorderManager" eventParams:params extParams:nil];
}
return;
}
if (status == 2) { //sdk
if (failure) {
failure(@{@"errMsg" : @"unauthorized disableauthorized,SDK被禁止申请麦克风权限"});
}
return;
}
dataDict = [self checkAACAuioParams:dataDict];
[[FATExtRecordManager shareManager] startRecordWithData:dataDict appletId:appInfo.appId eventBlock:^(NSInteger eventType, NSString *eventName, NSDictionary *paramDic, NSDictionary *extDic) {
if (self.context) {
[self.context sendResultEvent:eventType eventName:eventName eventParams:paramDic extParams:extDic];
}
}];
}];
} else if ([method isEqualToString:@"pause"]) {
[[FATExtRecordManager shareManager] pauseRecordWithData:dataDict appletId:appInfo.appId];
} else if ([method isEqualToString:@"resume"]) {
[[FATExtRecordManager shareManager] resumeRecordWithData:dataDict appletId:appInfo.appId];
} else if ([method isEqualToString:@"stop"]) {
[[FATExtRecordManager shareManager] stopRecordWithData:dataDict appletId:appInfo.appId];
} else if ([method isEqualToString:@"onFrameRecordedRemove"]) {
[[FATExtRecordManager shareManager] sendRecordFrameBufferWithData:dataDict appletId:appInfo.appId];
}
}
/// aacsampleRate800016000
/// - Parameter dic:
- (NSDictionary *)checkAACAuioParams:(NSDictionary *)dic {
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithDictionary:dic];
if ([dic[@"format"] isEqualToString:@"aac"]) {
NSString *encodeBitRate = dic[@"encodeBitRate"];
NSString *sampleRate = dic[@"sampleRate"];
NSString *numberOfChannels = dic[@"numberOfChannels"];
if ([encodeBitRate isEqualToString:@"48000"] && [numberOfChannels isEqualToString:@"2"] && [sampleRate isEqualToString:@"8000"]) {
[data setValue:@"16000" forKey:@"sampleRate"];
}
}
return data;
}
@end

View File

@ -1,16 +0,0 @@
//
// Copyright (c) 2017, finogeeks.com
// All rights reserved.
//
//
//
#import "FATExtBaseApi.h"
/**
wx.stopRecord1
*/
@interface FATExt_startRecord : FATExtBaseApi
@end

View File

@ -1,44 +0,0 @@
//
// Copyright (c) 2017, finogeeks.com
// All rights reserved.
//
//
//
#import "FATExt_startRecord.h"
#import "FATExtAVManager.h"
#import "FATClient+ext.h"
#import <AVFoundation/AVFoundation.h>
@implementation FATExt_startRecord
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
[[FATClient sharedClient] fat_requestAppletAuthorize:FATAuthorizationTypeMicrophone appletId:appInfo.appId complete:^(NSInteger status) {
if (status == 1) {
if (failure) {
failure(@{@"errMsg" : @"unauthorized,用户未授予麦克风权限"});
}
return;
} else if (status == 2) {
if (failure) {
failure(@{@"errMsg" : @"unauthorized disableauthorized,SDK被禁止申请麦克风权限"});
}
return;
}
[[FATExtAVManager sharedManager] startRecordWithSuccess:^(NSString *tempFilePath) {
if (success) {
success(@{@"tempFilePath" : tempFilePath});
}
} fail:^(NSString *msg) {
if (failure) {
failure(@{@"errMsg" : msg});
}
}];
}];
}
@end

View File

@ -1,15 +0,0 @@
//
// Copyright (c) 2017, finogeeks.com
// All rights reserved.
//
//
//
#import "FATExtBaseApi.h"
/**
*/
@interface FATExt_stopRecord : FATExtBaseApi
@end

View File

@ -1,22 +0,0 @@
//
// Copyright (c) 2017, finogeeks.com
// All rights reserved.
//
//
//
#import "FATExt_stopRecord.h"
#import "FATExtAVManager.h"
@implementation FATExt_stopRecord
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
[[FATExtAVManager sharedManager] stopRecord];
if (success) {
success(@{});
}
}
@end

View File

@ -1,17 +0,0 @@
//
// FATExtNavigationController.h
// FinAppletExt
//
// Created by 耀 on 2022/10/28.
// Copyright © 2022 finogeeks. All rights reserved.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FATExtNavigationController : UINavigationController
@end
NS_ASSUME_NONNULL_END

View File

@ -1,32 +0,0 @@
//
// FATExtNavigationController.m
// FinAppletExt
//
// Created by 耀 on 2022/10/28.
// Copyright © 2022 finogeeks. All rights reserved.
//
#import "FATExtNavigationController.h"
@interface FATExtNavigationController ()
@end
@implementation FATExtNavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
//
- (BOOL)shouldAutorotate {
return NO;
}
//
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
@end

View File

@ -1,38 +0,0 @@
//
// FATExt_LocationUpdateManager.h
// FinAppletExt
//
// Created by 耀 on 2022/11/6.
//
#import <Foundation/Foundation.h>
#import "FATExtBaseApi.h"
#import "FATExtLocationManager.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_LocationUpdateManager : NSObject
+ (instancetype)sharedManager;
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@property (nonatomic, assign) BOOL locationIsInit;
@property (nonatomic, copy) NSString *appletId;
@property (nonatomic, weak) id<FATApiHanderContextDelegate> context;
- (void)startLocationUpdateType:(NSString *)type isAllowsBackgroundLocationUpdates:(BOOL)result withAppId:(NSString *)appId Success:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel;
- (void)onLocationUpdate;
- (void)stopLocationUpdate;
- (void)checkLocationState;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,200 +0,0 @@
//
// FATExt_LocationUpdateManager.m
// FinAppletExt
//
// Created by 耀 on 2022/11/6.
//
#import "FATExt_LocationUpdateManager.h"
#import <FinApplet/FinApplet.h>
#import "FATWGS84ConvertToGCJ02.h"
#import <FinApplet/FinApplet.h>
static FATExt_LocationUpdateManager *instance = nil;
NSString *const FATExtAppletUpdateBackgroudPermissions = @"FATAppletUpdateBackgroudPermissions";
@interface FATExt_LocationUpdateManager ()<CLLocationManagerDelegate>
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) void (^success)(NSDictionary<NSString *, id> *_Nonnull);
@property (nonatomic, copy) void (^failure)(NSDictionary *_Nullable);
@property (nonatomic, copy) void (^cancel)(NSDictionary *_Nullable);
@end
@implementation FATExt_LocationUpdateManager
+ (instancetype)sharedManager {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[[self class] alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
//
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appletClose:) name:FATAppletDestroyNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(permissionsUpdate:) name:FATExtAppletUpdateBackgroudPermissions object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appletEnterBackground:) name:FATAppletEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidForeground:) name:FATAppletForegroundNotification object:nil];
}
return self;
}
#pragma
- (void)appletClose:(NSNotification *)notification {
NSDictionary *dic = notification.userInfo;
NSString *appletId = [dic objectForKey:@"appletId"];
//
if (appletId && [appletId isEqualToString:self.appletId] && self.locationIsInit) {
[self stopLocationUpdate];
}
}
- (void)permissionsUpdate:(NSNotification *)notification {
NSDictionary *dic = notification.userInfo;
NSInteger type = [[dic objectForKey:@"type"] integerValue];
if (type == 0 ) {
[self stopLocationUpdate];
}
if (_locationManager.allowsBackgroundLocationUpdates && self.locationIsInit) {
if (type == 1) {
[self stopLocationUpdate];
}
}
}
- (void)appletEnterBackground:(NSNotification *)notification {
if (!_locationManager.allowsBackgroundLocationUpdates && self.locationIsInit) {
[_locationManager stopUpdatingLocation];
}
}
- (void)appDidForeground:(NSNotification *)notification {
if (!_locationManager.allowsBackgroundLocationUpdates && self.locationIsInit) {
if ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways)) {
[_locationManager startUpdatingLocation];
}
}
}
- (void)checkLocationState {
if (self.locationIsInit) {
//
UIViewController *vc = [[UIApplication sharedApplication] fat_topViewController];
UINavigationController<FATCapsuleViewProtocol> *nav = (UINavigationController<FATCapsuleViewProtocol> *)vc.navigationController;
if ([nav respondsToSelector:@selector(controlCapsuleStateButton:state:animate:)]) {
[nav controlCapsuleStateButton:NO state:FATCapsuleButtonStateLocation animate:YES];
}
}
}
- (void)startLocationUpdateType:(NSString *)type isAllowsBackgroundLocationUpdates:(BOOL)result withAppId:(NSString *)appId Success:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
//
if (self.locationIsInit && _locationManager.allowsBackgroundLocationUpdates == result) {
return;
}
//
_locationManager = [[FATExtLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
_locationManager.allowsBackgroundLocationUpdates = result;
_locationManager.pausesLocationUpdatesAutomatically = YES;
[_locationManager requestWhenInUseAuthorization];
self.type = type;
self.locationIsInit = YES;
if ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedAlways)) {
[self onLocationUpdate];
}
self.appletId = appId;
self.success = success;
self.failure = failure;
}
- (void)onLocationUpdate {
[_locationManager startUpdatingLocation];
}
- (void)stopLocationUpdate {
[_locationManager stopUpdatingLocation];
if (self.context) {
[self.context sendResultEvent:0 eventName:@"offLocationChange" eventParams:@{} extParams:nil];
}
self.appletId = @"";
self.locationIsInit = NO;
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *newLocation = [locations objectAtIndex:0];
// gcj02
NSString *typeString = @"gcj02";
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:[newLocation coordinate]];
newLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
if ([self.type isEqualToString:@"wgs84"]) {
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromGCJToWGS:[newLocation coordinate]];
newLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
typeString = @"wgs84";
}
CLLocationCoordinate2D coordinate = newLocation.coordinate;
NSDictionary *params = @{@"altitude" : @(newLocation.altitude),
@"latitude" : @(coordinate.latitude),
@"longitude" : @(coordinate.longitude),
@"speed" : @(newLocation.speed),
@"accuracy" : @(newLocation.horizontalAccuracy),
@"type" : typeString,
@"verticalAccuracy" : @(newLocation.verticalAccuracy),
@"horizontalAccuracy" : @(newLocation.horizontalAccuracy)
};
if (self.context) {
[self.context sendResultEvent:0 eventName:@"onLocationChange" eventParams:params extParams:nil];
}
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if (self.context) {
[self.context sendResultEvent:0 eventName:@"onLocationChangeError" eventParams:@{} extParams:nil];
}
[self stopLocationUpdate];
if (self.failure) {
self.failure(@{});
}
}
//- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
// if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
// [self onLocationUpdate];
// if (self.success) {
// self.success(@{});
// }
// } else {
// if (self.failure) {
// self.failure(@{@"errMsg" : @"system permission denied"});
// }
// [self stopLocationUpdate];
// }
//}
@end

View File

@ -1,17 +0,0 @@
//
// FATExt_chooseLocation.h
// FinAppletExt
//
// Created by Haley on 2020/8/19.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtBaseApi.h"
@interface FATExt_chooseLocation : FATExtBaseApi
///
@property (nonatomic, strong) NSString *latitude;
///
@property (nonatomic, strong) NSString *longitude;
@end

View File

@ -1,107 +0,0 @@
//
// FATExt_chooseLocation.m
// FinAppletExt
//
// Created by Haley on 2020/8/19.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExt_chooseLocation.h"
#import "FATMapViewController.h"
#import "FATClient+ext.h"
#import "FATExtMapManager.h"
#import "FATExtNavigationController.h"
#import "FATExt_locationAuthManager.h"
#import <CoreLocation/CoreLocation.h>
@implementation FATExt_chooseLocation
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
// if (![CLLocationManager locationServicesEnabled]) {
// if (callback) {
// callback(FATExtensionCodeFailure, @{@"errMsg" : @"location service not open"});
// }
// return;
// }
NSString *mapClassStr = NSStringFromClass([FATExtMapManager shareInstance].mapClass);
NSString *apiName = nil;
if ([mapClassStr isEqualToString:@"FATBDMapView"]) {
apiName = @"FATBDExt_chooseLocation";
} else if ([mapClassStr isEqualToString:@"FATTXMapView"]) {
apiName = @"FATTXExt_chooseLocation";
} else if ([mapClassStr isEqualToString:@"FATGDMapView"]) {
apiName = @"FATGDExt_chooseLocation";
}
NSLog(@"sean=========FATExt_chooseLocation");
if (apiName) {
id<FATApiProtocol> api = [self.class fat_apiWithApiClass:apiName params:self.param];
if (api) {
api.appletInfo = self.appletInfo;
api.context = self.context;
[api setupApiWithSuccess:success failure:failure cancel:cancel];
return;
}
}
[[NSNotificationCenter defaultCenter]removeObserver:self];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleNotification:) name:@"PHIZ_NOTIFICATION_LOCATION_AUTHORIZE_END" object:nil];
[[NSNotificationCenter defaultCenter] postNotificationName:@"PHIZ_NOTIFICATION_LOCATION_AUTHORIZE" object:NULL userInfo:@{@"type":@"chooseLocation"}];
[[FATClient sharedClient] fat_requestAppletAuthorize:FATAuthorizationTypeLocation appletId:self.appletInfo.appId complete:^(NSInteger status) {
if (status == 0) {
[[FATExt_locationAuthManager shareInstance] fat_requestAppletLocationAuthorize:self.appletInfo isBackground:NO withComplete:^(BOOL status) {
if (status) {
[self callChooseLocationWithSuccess:success failure:failure cancel:cancel];
} else {
if (failure) {
failure(@{@"errMsg" : @"system permission denied"});
}
}
}];
} else if (status == 1) {
//
if (failure) {
failure(@{@"errMsg" : @"unauthorized,用户未授予位置权限"});
}
} else {
if (failure) {
failure(@{@"errMsg" : @"unauthorized disableauthorized,SDK被禁止申请位置权限"});
}
}
}];
}
- (void)callChooseLocationWithSuccess:(void (^)(NSDictionary<NSString *, id> *_Nonnull))success failure:(void (^)(NSDictionary *_Nullable))failure cancel:(void (^)(NSDictionary *cancelResult))cancel {
//
UIViewController *topVC = [[UIApplication sharedApplication] fat_topViewController];
FATMapViewController *mapVC = [[FATMapViewController alloc] init];
mapVC.latitude = self.latitude;
mapVC.longitude = self.longitude;
mapVC.cancelBlock = ^{
cancel(nil);
};
mapVC.sureBlock = ^(NSDictionary *locationInfo) {
success(locationInfo);
};
FATExtNavigationController *nav = [[FATExtNavigationController alloc] initWithRootViewController:mapVC];
if (@available(iOS 15, *)) {
UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init];
[barAppearance configureWithOpaqueBackground];
barAppearance.backgroundColor = [UIColor whiteColor];
nav.navigationBar.standardAppearance = barAppearance;
nav.navigationBar.scrollEdgeAppearance = barAppearance;
}
[topVC presentViewController:nav animated:YES completion:nil];
}
- (void)handleNotification:(NSNotification *)notification {
NSLog(@"sean=========handleNotification");
}
@end

View File

@ -1,16 +0,0 @@
//
// FATExt_choosePoi.h
// FinAppletExt
//
// Created by 耀 on 2021/12/7.
//
#import "FATExtBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_choosePoi : FATExtBaseApi
@end
NS_ASSUME_NONNULL_END

View File

@ -1,94 +0,0 @@
//
// FATExt_choosePoi.m
// FinAppletExt
//
// Created by 耀 on 2021/12/7.
//
#import "FATExt_choosePoi.h"
#import "FATLocationManager.h"
#import "FATWGS84ConvertToGCJ02.h"
#import "FATClient+ext.h"
#import "FATExtChoosePoiViewController.h"
#import "FATExtMapManager.h"
#import "FATExtNavigationController.h"
#import "FATExt_locationAuthManager.h"
#import <FinApplet/FinApplet.h>
@implementation FATExt_choosePoi
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
// FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
//使sdkAPI
NSString *mapClassStr = NSStringFromClass([FATExtMapManager shareInstance].mapClass);
NSString *apiName = nil;
if ([mapClassStr isEqualToString:@"FATBDMapView"]) {
apiName = @"FATBDExt_choosePoi";
} else if ([mapClassStr isEqualToString:@"FATTXMapView"]) {
apiName = @"FATTXExt_choosePoi";
}
if (apiName) {
id<FATApiProtocol> api = [self.class fat_apiWithApiClass:apiName params:self.param];
if (api) {
api.appletInfo = self.appletInfo;
api.context = self.context;
[api setupApiWithSuccess:success failure:failure cancel:cancel];
return;
}
}
NSLog(@"sean=========FATExt_choosePoi");
[[FATClient sharedClient] fat_requestAppletAuthorize:FATAuthorizationTypeLocation appletId:self.appletInfo.appId complete:^(NSInteger status) {
if (status == 0) {
//
[[FATExt_locationAuthManager shareInstance] fat_requestAppletLocationAuthorize:self.appletInfo isBackground:NO withComplete:^(BOOL status) {
if (status) {
[self callChooseLocationWithWithSuccess:success failure:failure cancel:cancel];
} else {
if (failure) {
failure(@{@"errMsg" : @"system permission denied"});
}
}
}];
} else if (status == 1) {
//
if (failure) {
failure(@{@"errMsg" : @"unauthorized,用户未授予位置权限"});
}
} else {
if (failure) {
failure(@{@"errMsg" : @"unauthorized disableauthorized,SDK被禁止申请位置权限"});
}
}
}];
}
- (void)callChooseLocationWithWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
//
UIViewController *topVC = [[UIApplication sharedApplication] fat_topViewController];
FATExtChoosePoiViewController *mapVC = [[FATExtChoosePoiViewController alloc] init];
mapVC.cancelBlock = ^{
cancel(nil);
};
mapVC.sureBlock = ^(NSDictionary *locationInfo) {
success(locationInfo);
};
FATExtNavigationController *nav = [[FATExtNavigationController alloc] initWithRootViewController:mapVC];
if (@available(iOS 15, *)) {
UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init];
[barAppearance configureWithOpaqueBackground];
barAppearance.backgroundColor = [UIColor whiteColor];
nav.navigationBar.standardAppearance = barAppearance;
nav.navigationBar.scrollEdgeAppearance = barAppearance;
}
[topVC presentViewController:nav animated:YES completion:nil];
}
@end

View File

@ -1,22 +0,0 @@
//
// FATExt_getLocation.h
// FinAppletExt
//
// Created by Haley on 2020/12/10.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExtBaseApi.h"
@interface FATExt_getLocation : FATExtBaseApi
@property (nonatomic, copy) NSString *type;
@property (nonatomic, assign) BOOL altitude;
@property (nonatomic, assign) BOOL isHighAccuracy;
@property (nonatomic, assign) NSInteger highAccuracyExpireTime;
@end

View File

@ -1,153 +0,0 @@
//
// FATExt_getLocation.m
// FinAppletExt
//
// Created by Haley on 2020/12/10.
// Copyright © 2020 finogeeks. All rights reserved.
//
#import "FATExt_getLocation.h"
#import "FATLocationManager.h"
#import "FATWGS84ConvertToGCJ02.h"
#import "FATClient+ext.h"
#import "FATExtLocationManager.h"
#import "FATExtMapManager.h"
#import "FATExt_locationAuthManager.h"
#import <FinApplet/FinApplet.h>
@interface FATExt_getLocation () <CLLocationManagerDelegate>
@property (nonatomic, strong) FATExtLocationManager *locationManager;
@property (nonatomic, strong) FATExtBaseApi *strongSelf;
@property (nonatomic, copy) void (^success)(NSDictionary<NSString *, id> *_Nonnull);
@property (nonatomic, copy) void (^failure)(NSDictionary *_Nullable);
@property (nonatomic, strong) NSTimer *locationUpdateTimer;
@end
@implementation FATExt_getLocation
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
NSString *mapClassStr = NSStringFromClass([FATExtMapManager shareInstance].mapClass);
NSString *apiName = nil;
if ([mapClassStr isEqualToString:@"FATBDMapView"]) {
apiName = @"FATBDExt_getLocation";
} else if ([mapClassStr isEqualToString:@"FATTXMapView"]) {
apiName = @"FATTXExt_getLocation";
} else if ([mapClassStr isEqualToString:@"FATGDMapView"]) {
apiName = @"FATGDExt_getLocation";
}
if (apiName) {
id<FATApiProtocol> api = [self.class fat_apiWithApiClass:apiName params:self.param];
if (api) {
api.appletInfo = self.appletInfo;
api.context = self.context;
[api setupApiWithSuccess:success failure:failure cancel:cancel];
return;
}
}
self.success = success;
self.failure = failure;
[[NSNotificationCenter defaultCenter]removeObserver:self];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(handleNotification:) name:@"PHIZ_NOTIFICATION_LOCATION_AUTHORIZE_END" object:nil];
// FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
[[NSNotificationCenter defaultCenter] postNotificationName:@"PHIZ_NOTIFICATION_LOCATION_AUTHORIZE" object:NULL userInfo:@{@"type":@"gteLocation"}];
NSLog(@"sean=========FATExt_getLocation");
[[FATClient sharedClient] fat_requestAppletAuthorize:FATAuthorizationTypeLocation appletId:self.appletInfo.appId complete:^(NSInteger status) {
if (status == 0) {
//
[[FATExt_locationAuthManager shareInstance] fat_requestAppletLocationAuthorize:self.appletInfo isBackground:NO withComplete:^(BOOL status) {
if (status) {
[self startUpdateLocation];
} else {
if (failure) {
failure(@{@"errMsg" : @"system permission denied"});
}
}
}];
} else if (status == 1) {
//
if (failure) {
failure(@{@"errMsg" : @"unauthorized,用户未授予位置权限"});
}
} else {
if (failure) {
failure(@{@"errMsg" : @"unauthorized disableauthorized,SDK被禁止申请位置权限"});
}
}
}];
}
- (void)startUpdateLocation {
_locationManager = [[FATExtLocationManager alloc] init];
_locationManager.delegate = self;
if (self.isHighAccuracy) {
_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
} else {
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
}
[_locationManager requestWhenInUseAuthorization];
[_locationManager startUpdatingLocation];
_strongSelf = self;
__weak typeof(self) weak_self = self;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 10);
dispatch_after(time, dispatch_get_global_queue(0, 0), ^{
weak_self.strongSelf = nil;
});
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
CLLocation *newLocation = [locations objectAtIndex:0];
NSString *typeString = @"wgs84";
//
if ([self.type isEqualToString:@"gcj02"]) {
//coord
CLLocationCoordinate2D coord = [FATWGS84ConvertToGCJ02ForAMapView transformFromWGSToGCJ:[newLocation coordinate]];
newLocation = [[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude];
typeString = @"gcj02";
}
[FATLocationManager manager].location = newLocation;
CLLocationCoordinate2D coordinate = newLocation.coordinate;
if (self.success) {
NSDictionary *params = @{@"altitude" : @(newLocation.altitude),
@"latitude" : @(coordinate.latitude),
@"longitude" : @(coordinate.longitude),
@"speed" : @(newLocation.speed),
@"accuracy" : @(newLocation.horizontalAccuracy),
@"type" : typeString,
@"verticalAccuracy" : @(newLocation.verticalAccuracy),
@"horizontalAccuracy" : @(newLocation.horizontalAccuracy)
};
NSMutableDictionary *dataDic = [[NSMutableDictionary alloc] initWithDictionary:params];
if (!self.altitude) {
[dataDic removeObjectForKey:@"altitude"];
}
self.success(dataDic);
}
[_locationManager stopUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
if (self.failure) {
self.failure(nil);
}
}
- (void)handleNotification:(NSNotification *)notification {
NSLog(@"sean=========handleNotification");
}
@end

View File

@ -1,21 +0,0 @@
//
// FATExt_locationAuthManager.h
// FinAppletExt
//
// Created by 耀 on 2022/12/24.
//
#import <Foundation/Foundation.h>
#import <FinApplet/FinApplet.h>
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_locationAuthManager : NSObject
+ (instancetype)shareInstance;
- (void)fat_requestAppletLocationAuthorize:(FATAppletInfo *)appletInfo isBackground:(BOOL)isBackground withComplete:(void (^)(BOOL status))complete;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,136 +0,0 @@
//
// FATExt_locationAuthManager.m
// FinAppletExt
//
// Created by 耀 on 2022/12/24.
//
#import "FATExt_locationAuthManager.h"
#import <CoreLocation/CoreLocation.h>
@interface FATExt_locationAuthManager () <CLLocationManagerDelegate>
@property (nonatomic, strong) CLLocationManager *locationManager;
@property (nonatomic, strong) NSMutableArray *locationAuthCompleteArray;
@property (nonatomic, strong) NSMutableArray<FATAppletInfo*> *appletInfoArray;
@property (nonatomic, strong) NSMutableDictionary *authTypeDic; //keyId value
@end
static FATExt_locationAuthManager *instance = nil;
@implementation FATExt_locationAuthManager
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[FATExt_locationAuthManager alloc] init];
});
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super allocWithZone:zone];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
[self p_init];
}
return self;
}
- (void)p_init {
_locationAuthCompleteArray = [NSMutableArray array];
_appletInfoArray = [[NSMutableArray alloc]init];
_authTypeDic = [[NSMutableDictionary alloc]init];
}
- (void)fat_requestAppletLocationAuthorize:(FATAppletInfo *)appletInfo isBackground:(BOOL)isBackground withComplete:(void (^)(BOOL status))complete {
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
[self notifyApp:appletInfo authType:isBackground ? FATAuthorizationTypeLocationBackground : FATAuthorizationTypeLocation authResult:FATAuthorizationStatusAuthorized];
if (complete) {
complete(YES);
}
return;
}
if (status != kCLAuthorizationStatusNotDetermined) {
[self notifyApp:appletInfo authType:isBackground ? FATAuthorizationTypeLocationBackground : FATAuthorizationTypeLocation authResult:FATAuthorizationStatusDenied];
if (complete) {
complete(NO);
}
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.locationAuthCompleteArray addObject:complete];
if (appletInfo) {
[self.appletInfoArray addObject:appletInfo];
if (appletInfo.appId) {
[self.authTypeDic setValue:isBackground ? @(FATAuthorizationTypeLocationBackground) : @(FATAuthorizationTypeLocation) forKey:appletInfo.appId];
}
}
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
[self.locationManager requestWhenInUseAuthorization];
});
return;
}
- (void)notifyApp:(FATAppletInfo *)appletInfo authType:(FATAuthorizationType)type authResult:(FATAuthorizationStatus)result {
id<FATAppletAuthDelegate> delegate = [FATClient sharedClient].authDelegate;
if (delegate && [delegate respondsToSelector:@selector(applet:didRequestAuth:withResult:)]) {
[delegate applet:appletInfo didRequestAuth:type withResult:result];
}
}
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusNotDetermined) {
return;
}
for (FATAppletInfo *appInfo in self.appletInfoArray) {
FATAuthorizationStatus authStatus = FATAuthorizationStatusDenied;
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
authStatus = FATAuthorizationStatusAuthorized;
}
NSNumber *authtype = [self.authTypeDic objectForKey:appInfo.appId];
FATAuthorizationType type = FATAuthorizationTypeLocation;
if (authtype) {
type = [authtype integerValue];
}
[self notifyApp:appInfo authType:type authResult:authStatus];
}
[self.appletInfoArray removeAllObjects];
[self.authTypeDic removeAllObjects];
if (status == kCLAuthorizationStatusAuthorizedWhenInUse || status == kCLAuthorizationStatusAuthorizedAlways) {
for (int i = 0; i < self.locationAuthCompleteArray.count; i++) {
void(^locationComplete)(BOOL status) = self.locationAuthCompleteArray[i];
locationComplete(YES);
}
[self.locationAuthCompleteArray removeAllObjects];
return;
}
for (int i = 0; i < self.locationAuthCompleteArray.count; i++) {
void(^locationComplete)(BOOL status) = self.locationAuthCompleteArray[i];
locationComplete(NO);
}
[self.locationAuthCompleteArray removeAllObjects];
}
@end

View File

@ -1,18 +0,0 @@
//
// FATExt_locationChange.h
// FinAppletExt
//
// Created by 耀 on 2022/11/6.
//
#import "FATExtBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_locationChange : FATExtBaseApi
@property (nonatomic, assign) BOOL enable;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,30 +0,0 @@
//
// FATExt_locationChange.m
// FinAppletExt
//
// Created by 耀 on 2022/11/6.
//
#import "FATExt_locationChange.h"
#import "FATClient+ext.h"
#import "FATExt_LocationUpdateManager.h"
@implementation FATExt_locationChange
- (void)setupApiWithSuccess:(void (^)(NSDictionary<NSString *, id> *successResult))success
failure:(void (^)(NSDictionary *failResult))failure
cancel:(void (^)(NSDictionary *cancelResult))cancel {
// if (self.enable) {
// [FATExt_LocationUpdateManager sharedManager].context = self.context;
// [[FATExt_LocationUpdateManager sharedManager] onLocationUpdate];
// } else {
// [FATExt_LocationUpdateManager sharedManager].context = self.context;
// [[FATExt_LocationUpdateManager sharedManager] stopLocationUpdate];
// }
if (success) {
success(@{});
}
}
@end

View File

@ -1,27 +0,0 @@
//
// FATExt_openLocation.h
// FinAppletExt
//
// Created by 耀 on 2021/12/7.
//
#import "FATExtBaseApi.h"
NS_ASSUME_NONNULL_BEGIN
@interface FATExt_openLocation : FATExtBaseApi
///
@property (nonatomic, strong) NSString *latitude;
///
@property (nonatomic, strong) NSString *longitude;
@property (nonatomic, strong) NSString *scale;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *address;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More