feat: add Android one-click login with dialog mode
- Integrate ali_auth plugin as local package (previously pub dependency) - Fix AppCompatActivity ClassNotFoundException via proguard keep rules - Add dialog popup mode matching iOS style (white background, rounded corners) - Fix invisible login button by adding blue GradientDrawable background - Add Airhub logo to authorization dialog via logoImgPath - Fix auth page not closing after login by calling quitPage() on token success - Update .gitignore to exclude plugin examples, screenshots, docs and backups Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
28
airhub_app/.gitignore
vendored
@ -43,3 +43,31 @@ app.*.map.json
|
|||||||
/android/app/debug
|
/android/app/debug
|
||||||
/android/app/profile
|
/android/app/profile
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
|
# ali_auth plugin - 不需要提交的文件
|
||||||
|
packages/ali_auth/example/
|
||||||
|
packages/ali_auth/screenshots/
|
||||||
|
packages/ali_auth/doc/
|
||||||
|
packages/ali_auth/.github/
|
||||||
|
packages/ali_auth/.metadata
|
||||||
|
packages/ali_auth/.pubignore
|
||||||
|
packages/ali_auth/.gitignore
|
||||||
|
packages/ali_auth/CHANGELOG.md
|
||||||
|
packages/ali_auth/CHANGELOG-zh.md
|
||||||
|
packages/ali_auth/CODE_OF_CONDUCT.md
|
||||||
|
packages/ali_auth/LICENSE
|
||||||
|
packages/ali_auth/README.md
|
||||||
|
packages/ali_auth/README_en.md
|
||||||
|
packages/ali_auth/release.md
|
||||||
|
packages/ali_auth/test/
|
||||||
|
|
||||||
|
# ali_auth 旧备份
|
||||||
|
packages/ali_auth_backup_*/
|
||||||
|
|
||||||
|
# 调试文档和构建脚本
|
||||||
|
ONECLICK_LOGIN_DEBUG.md
|
||||||
|
TEST_ONECLICK_LOGIN.md
|
||||||
|
UPDATE_ALIYUN_SDK.md
|
||||||
|
build_and_install_ios.sh
|
||||||
|
build_android_release.sh
|
||||||
|
rebuild_ios.sh
|
||||||
|
|||||||
@ -35,10 +35,16 @@ android {
|
|||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
|
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// 阿里云一键登录SDK的授权页需要 AppCompatActivity
|
||||||
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
|
}
|
||||||
|
|
||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|||||||
6
airhub_app/android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# 阿里云一键登录SDK - 授权页需要 AppCompatActivity
|
||||||
|
-keep class androidx.appcompat.** { *; }
|
||||||
|
-keep class com.mobile.auth.** { *; }
|
||||||
|
-keep class com.cmic.** { *; }
|
||||||
|
-keep class com.alibaba.sdk.android.** { *; }
|
||||||
|
-keep class com.alicom.** { *; }
|
||||||
BIN
airhub_app/assets/www/auth_bg_gradient.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
airhub_app/assets/www/login_btn_normal.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
airhub_app/assets/www/login_btn_press.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
airhub_app/assets/www/login_btn_unable.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
@ -1,4 +1,8 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- ali_auth (1.3.7):
|
||||||
|
- Flutter
|
||||||
|
- MJExtension
|
||||||
|
- SDWebImage
|
||||||
- audio_session (0.0.1):
|
- audio_session (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
@ -10,8 +14,12 @@ PODS:
|
|||||||
- just_audio (0.0.1):
|
- just_audio (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- MJExtension (3.4.2)
|
||||||
- permission_handler_apple (9.3.0):
|
- permission_handler_apple (9.3.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- SDWebImage (5.21.6):
|
||||||
|
- SDWebImage/Core (= 5.21.6)
|
||||||
|
- SDWebImage/Core (5.21.6)
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@ -20,6 +28,7 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- ali_auth (from `.symlinks/plugins/ali_auth/ios`)
|
||||||
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
- flutter_blue_plus_darwin (from `.symlinks/plugins/flutter_blue_plus_darwin/darwin`)
|
- flutter_blue_plus_darwin (from `.symlinks/plugins/flutter_blue_plus_darwin/darwin`)
|
||||||
@ -29,7 +38,14 @@ DEPENDENCIES:
|
|||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- MJExtension
|
||||||
|
- SDWebImage
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
ali_auth:
|
||||||
|
:path: ".symlinks/plugins/ali_auth/ios"
|
||||||
audio_session:
|
audio_session:
|
||||||
:path: ".symlinks/plugins/audio_session/ios"
|
:path: ".symlinks/plugins/audio_session/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
@ -48,12 +64,15 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
|
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
ali_auth: fe9a6188a90eb39227f3674c05a71383ac4ec6a2
|
||||||
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
|
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_blue_plus_darwin: 20a08bfeaa0f7804d524858d3d8744bcc1b6dbc3
|
flutter_blue_plus_darwin: 20a08bfeaa0f7804d524858d3d8744bcc1b6dbc3
|
||||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed
|
just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed
|
||||||
|
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
|
||||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||||
|
SDWebImage: 1bb6a1b84b6fe87b972a102bdc77dd589df33477
|
||||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d
|
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d
|
||||||
|
|
||||||
|
|||||||
@ -44,12 +44,27 @@ class ApiClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// POST 请求,返回 data 字段
|
/// POST 请求,返回 data 字段
|
||||||
|
/// 如果 path 以 http:// 或 https:// 开头,则作为完整 URL 使用
|
||||||
Future<dynamic> post(
|
Future<dynamic> post(
|
||||||
String path, {
|
String path, {
|
||||||
dynamic data,
|
dynamic data,
|
||||||
}) async {
|
}) async {
|
||||||
final response = await _request(
|
final response = await _request(
|
||||||
() => _dio.post(path, data: data),
|
() {
|
||||||
|
// 如果是完整 URL,使用 Options 覆盖 baseUrl
|
||||||
|
if (path.startsWith('http://') || path.startsWith('https://')) {
|
||||||
|
return _dio.post(
|
||||||
|
path,
|
||||||
|
data: data,
|
||||||
|
options: Options(
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
// 使用空字符串作为 baseUrl,让 Dio 使用完整路径
|
||||||
|
extra: {'useFullUrl': true},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _dio.post(path, data: data);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
class ApiConfig {
|
class ApiConfig {
|
||||||
/// 后端服务器地址(开发环境请替换为实际 IP)
|
/// 后端服务器地址(本地开发环境)
|
||||||
static const String baseUrl = 'http://192.168.124.8:8000';
|
static const String baseUrl = 'http://192.168.124.8:8000';
|
||||||
|
|
||||||
|
/// 一键授权登录专用域名(HTTPS,用于阿里云号码认证)
|
||||||
|
static const String authBaseUrl = 'https://qiyuan-rtc-api.airlabs.art';
|
||||||
|
|
||||||
/// App 端 API 前缀
|
/// App 端 API 前缀
|
||||||
static const String apiPrefix = '/api/v1';
|
static const String apiPrefix = '/api/v1';
|
||||||
|
|
||||||
@ -13,4 +16,7 @@ class ApiConfig {
|
|||||||
|
|
||||||
/// 拼接完整 URL
|
/// 拼接完整 URL
|
||||||
static String get fullBaseUrl => '$baseUrl$apiPrefix';
|
static String get fullBaseUrl => '$baseUrl$apiPrefix';
|
||||||
|
|
||||||
|
/// 拼接一键授权登录完整 URL
|
||||||
|
static String get fullAuthBaseUrl => '$authBaseUrl$apiPrefix';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/foundation.dart' show debugPrint, kIsWeb;
|
import 'package:flutter/foundation.dart' show debugPrint, kIsWeb;
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:ali_auth/ali_auth.dart';
|
||||||
// 本地 Web 调试:始终使用 stub(ali_auth 不兼容当前 Dart 版本)
|
|
||||||
import 'phone_auth_service_stub.dart';
|
|
||||||
|
|
||||||
part 'phone_auth_service.g.dart';
|
part 'phone_auth_service.g.dart';
|
||||||
|
|
||||||
@ -19,13 +17,132 @@ PhoneAuthService phoneAuthService(Ref ref) {
|
|||||||
return PhoneAuthService();
|
return PhoneAuthService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 登录流程的终止性错误码(收到即表示登录失败,需结束等待)
|
||||||
|
const _terminalErrorCodes = {
|
||||||
|
'600002', // 唤起授权页失败
|
||||||
|
'600004', // 获取运营商配置信息失败
|
||||||
|
'600005', // 手机终端不安全
|
||||||
|
'600007', // 未检测到SIM卡
|
||||||
|
'600008', // 蜂窝网络未开启
|
||||||
|
'600009', // 无法判断运营商
|
||||||
|
'600010', // 未知异常
|
||||||
|
'600011', // 获取token失败
|
||||||
|
'600012', // 预取号失败
|
||||||
|
'600013', // 运营商维护升级
|
||||||
|
'600014', // 已达最大调用次数
|
||||||
|
'600015', // 接口超时
|
||||||
|
'600017', // AppID/Appkey解析失败
|
||||||
|
'600018', // 请先初始化SDK
|
||||||
|
'600021', // 运营商已切换
|
||||||
|
'600023', // 加载自定义控件异常
|
||||||
|
'600025', // 检测参数错误
|
||||||
|
'600026', // 授权页已加载时不允许调用
|
||||||
|
'500000', // 参数获取异常
|
||||||
|
'500001', // 密钥不能为空
|
||||||
|
'500003', // 未初始化就调用延时登录
|
||||||
|
};
|
||||||
|
|
||||||
class PhoneAuthService {
|
class PhoneAuthService {
|
||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
String? _lastError;
|
String? _lastError;
|
||||||
|
|
||||||
|
/// 用于等待 initSdk 通过 EventChannel 返回结果
|
||||||
|
Completer<void>? _initCompleter;
|
||||||
|
|
||||||
|
/// 用于等待 login 通过 EventChannel 返回 token
|
||||||
|
Completer<String?>? _loginCompleter;
|
||||||
|
|
||||||
|
/// 收到的所有事件码(调试用)
|
||||||
|
final List<String> _eventLog = [];
|
||||||
|
|
||||||
/// 最近一次错误信息(用于 UI 展示)
|
/// 最近一次错误信息(用于 UI 展示)
|
||||||
String? get lastError => _lastError;
|
String? get lastError => _lastError;
|
||||||
|
|
||||||
|
/// 统一的 EventChannel 事件处理
|
||||||
|
void _handleEvent(dynamic event) {
|
||||||
|
debugPrint('[AliAuth] event: $event');
|
||||||
|
final code = event['code'] as String?;
|
||||||
|
if (code == null) return;
|
||||||
|
_eventLog.add('$code:${event['msg'] ?? ''}');
|
||||||
|
|
||||||
|
// ========== 终止性事件:登录成功 ==========
|
||||||
|
if (code == '600000') {
|
||||||
|
final token = event['data'] as String?;
|
||||||
|
if (token != null && token.isNotEmpty) {
|
||||||
|
debugPrint('[AliAuth] 登录成功,获取到 token');
|
||||||
|
// 主动关闭授权页面和loading(Android原生端未自动关闭)
|
||||||
|
AliAuth.quitPage();
|
||||||
|
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
|
||||||
|
_loginCompleter!.complete(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 终止性事件:用户取消 ==========
|
||||||
|
if (code == '700000') {
|
||||||
|
_lastError = '用户取消登录';
|
||||||
|
debugPrint('[AliAuth] $_lastError');
|
||||||
|
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
|
||||||
|
_loginCompleter!.complete(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 终止性事件:用户切换其他登录方式 ==========
|
||||||
|
if (code == '700001') {
|
||||||
|
_lastError = '切换其他方式';
|
||||||
|
debugPrint('[AliAuth] $_lastError');
|
||||||
|
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
|
||||||
|
_loginCompleter!.complete(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 终止性事件:授权页已销毁(安全兜底) ==========
|
||||||
|
if (code == '700020') {
|
||||||
|
debugPrint('[AliAuth] 授权页已销毁');
|
||||||
|
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
|
||||||
|
_lastError ??= '授权页已关闭';
|
||||||
|
_loginCompleter!.complete(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 终止性事件:已知错误码 ==========
|
||||||
|
if (_terminalErrorCodes.contains(code)) {
|
||||||
|
_lastError = '${event['msg'] ?? '错误码$code'}';
|
||||||
|
debugPrint('[AliAuth] 终止性错误: $_lastError');
|
||||||
|
if (_initCompleter != null && !_initCompleter!.isCompleted) {
|
||||||
|
_initCompleter!.completeError(_lastError!);
|
||||||
|
}
|
||||||
|
if (_loginCompleter != null && !_loginCompleter!.isCompleted) {
|
||||||
|
_loginCompleter!.complete(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 初始化阶段事件 ==========
|
||||||
|
if (code == '600016') {
|
||||||
|
debugPrint('[AliAuth] 预取号成功,SDK就绪');
|
||||||
|
if (_initCompleter != null && !_initCompleter!.isCompleted) {
|
||||||
|
_initCompleter!.complete();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 中间事件:仅记录日志,不影响流程 ==========
|
||||||
|
// 500004: SDK版本信息
|
||||||
|
// 600001: 唤起授权页成功
|
||||||
|
// 600024: 环境检查通过
|
||||||
|
// 700002: 用户点击登录按钮(中间态,等待SDK返回600000或错误)
|
||||||
|
// 700003: 用户勾选协议选项
|
||||||
|
// 700004: 用户点击协议富文本
|
||||||
|
// 700005: 点击第三方按钮
|
||||||
|
// 700006~700010: 二次弹窗相关事件
|
||||||
|
debugPrint('[AliAuth] 中间事件 $code: ${event['msg'] ?? ''}');
|
||||||
|
}
|
||||||
|
|
||||||
/// 初始化 SDK(只需调用一次)
|
/// 初始化 SDK(只需调用一次)
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
debugPrint('[AliAuth] init() called, _initialized=$_initialized, kIsWeb=$kIsWeb');
|
debugPrint('[AliAuth] init() called, _initialized=$_initialized, kIsWeb=$kIsWeb');
|
||||||
@ -35,16 +152,91 @@ class PhoneAuthService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_initCompleter = Completer<void>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await AliAuth.initSdk(
|
// 【关键】必须先建立 EventChannel 监听,再调用 initSdk
|
||||||
|
// iOS 原生 initSdk 要求 _eventSink 不为 nil,否则直接返回错误
|
||||||
|
AliAuth.loginListen(onEvent: _handleEvent);
|
||||||
|
|
||||||
|
// 不要 await initSdk —— iOS 原生端不通过 MethodChannel 返回结果
|
||||||
|
// 所有结果通过 EventChannel 返回
|
||||||
|
// isDelay:true → 仅做初始化+预取号,不弹出登录页
|
||||||
|
AliAuth.initSdk(
|
||||||
AliAuthModel(
|
AliAuthModel(
|
||||||
PhoneAuthConfig.androidSk,
|
PhoneAuthConfig.androidSk,
|
||||||
PhoneAuthConfig.iosSk,
|
PhoneAuthConfig.iosSk,
|
||||||
isDebug: true,
|
isDebug: true,
|
||||||
|
isDelay: true,
|
||||||
autoQuitPage: true,
|
autoQuitPage: true,
|
||||||
pageType: PageType.fullPort,
|
|
||||||
|
// ========== 弹窗模式(与 iOS 一致) ==========
|
||||||
|
pageType: PageType.dialogPort,
|
||||||
|
dialogWidth: 300,
|
||||||
|
dialogHeight: 340,
|
||||||
|
dialogCornerRadiusArray: [12, 12, 12, 12],
|
||||||
|
dialogAlpha: 0.5,
|
||||||
|
tapAuthPageMaskClosePage: true,
|
||||||
|
|
||||||
|
// ========== 导航栏(弹窗模式下隐藏) ==========
|
||||||
|
navHidden: true,
|
||||||
|
navReturnHidden: true,
|
||||||
|
|
||||||
|
// ========== Logo ==========
|
||||||
|
logoHidden: false,
|
||||||
|
logoImgPath: 'assets/www/logo.png',
|
||||||
|
logoWidth: 60,
|
||||||
|
logoHeight: 60,
|
||||||
|
logoOffsetY: 20,
|
||||||
|
|
||||||
|
// ========== 号码栏 ==========
|
||||||
|
numberColor: '#333333',
|
||||||
|
numFieldOffsetY: 95,
|
||||||
|
|
||||||
|
// ========== Slogan ==========
|
||||||
|
sloganHidden: true,
|
||||||
|
|
||||||
|
// ========== 登录按钮 ==========
|
||||||
|
logBtnText: '本机号码一键登录',
|
||||||
|
logBtnTextColor: '#FFFFFF',
|
||||||
|
logBtnWidth: 250,
|
||||||
|
logBtnHeight: 44,
|
||||||
|
logBtnOffsetY: 140,
|
||||||
|
|
||||||
|
// ========== 切换其他方式 ==========
|
||||||
|
switchAccText: '其他方式登录',
|
||||||
|
switchAccTextColor: '#999999',
|
||||||
|
switchOffsetY: 195,
|
||||||
|
|
||||||
|
// ========== 协议 ==========
|
||||||
|
privacyState: true,
|
||||||
|
privacyBefore: '我已阅读并同意',
|
||||||
|
privacyEnd: '',
|
||||||
|
vendorPrivacyPrefix: '《',
|
||||||
|
vendorPrivacySuffix: '》',
|
||||||
|
protocolOneName: '用户协议',
|
||||||
|
protocolOneURL: 'https://qiyuan-rtc-api.airlabs.art/agreement/',
|
||||||
|
protocolTwoName: '隐私政策',
|
||||||
|
protocolTwoURL: 'https://qiyuan-rtc-api.airlabs.art/privacy/',
|
||||||
|
privacyOffsetY_B: 15,
|
||||||
|
|
||||||
|
// ========== 背景 ==========
|
||||||
|
pageBackgroundPath: '',
|
||||||
|
backgroundColor: '#FFFFFF',
|
||||||
|
pageBackgroundRadius: 12,
|
||||||
|
isHiddenCustom: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 等待 EventChannel 返回预取号成功(600016)
|
||||||
|
await _initCompleter!.future.timeout(
|
||||||
|
const Duration(seconds: 10),
|
||||||
|
onTimeout: () {
|
||||||
|
throw TimeoutException(
|
||||||
|
'初始化超时(10s) events=${_eventLog.join(",")}');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
_lastError = null;
|
_lastError = null;
|
||||||
debugPrint('[AliAuth] SDK 初始化成功');
|
debugPrint('[AliAuth] SDK 初始化成功');
|
||||||
@ -52,6 +244,8 @@ class PhoneAuthService {
|
|||||||
_initialized = false;
|
_initialized = false;
|
||||||
_lastError = 'SDK初始化失败: $e';
|
_lastError = 'SDK初始化失败: $e';
|
||||||
debugPrint('[AliAuth] $_lastError');
|
debugPrint('[AliAuth] $_lastError');
|
||||||
|
} finally {
|
||||||
|
_initCompleter = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,34 +261,25 @@ class PhoneAuthService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final completer = Completer<String?>();
|
_loginCompleter = Completer<String?>();
|
||||||
|
|
||||||
AliAuth.loginListen(onEvent: (event) {
|
// 调用 login() 弹出运营商授权页面
|
||||||
debugPrint('[AliAuth] loginListen event: $event');
|
// 不要 await —— iOS 原生端不通过 MethodChannel 返回结果
|
||||||
final code = event['code'] as String?;
|
try {
|
||||||
|
debugPrint('[AliAuth] 调用 AliAuth.login() 触发登录');
|
||||||
if (code == '600000' && event['data'] != null) {
|
AliAuth.login();
|
||||||
if (!completer.isCompleted) {
|
} catch (e) {
|
||||||
completer.complete(event['data'] as String);
|
_lastError = '调用登录失败: $e';
|
||||||
}
|
|
||||||
} else if (code == '700000' || code == '700001') {
|
|
||||||
_lastError = '用户取消';
|
|
||||||
if (!completer.isCompleted) {
|
|
||||||
completer.complete(null);
|
|
||||||
}
|
|
||||||
} else if (code != null && code.startsWith('6') && code != '600000') {
|
|
||||||
_lastError = '错误码$code: ${event['msg']}';
|
|
||||||
debugPrint('[AliAuth] $_lastError');
|
debugPrint('[AliAuth] $_lastError');
|
||||||
if (!completer.isCompleted) {
|
if (!_loginCompleter!.isCompleted) {
|
||||||
completer.complete(null);
|
_loginCompleter!.complete(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return completer.future.timeout(
|
return _loginCompleter!.future.timeout(
|
||||||
const Duration(seconds: 30),
|
const Duration(seconds: 15),
|
||||||
onTimeout: () {
|
onTimeout: () {
|
||||||
_lastError = '请求超时(30s)';
|
_lastError = '登录超时(15s) events=${_eventLog.join(",")}';
|
||||||
debugPrint('[AliAuth] $_lastError');
|
debugPrint('[AliAuth] $_lastError');
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
class AliAuth {
|
class AliAuth {
|
||||||
static Future<void> initSdk(dynamic model) async {}
|
static Future<void> initSdk(dynamic model) async {}
|
||||||
static void loginListen({required Function(Map<String, dynamic>) onEvent}) {}
|
static void loginListen({required Function(Map<String, dynamic>) onEvent}) {}
|
||||||
|
static Future<dynamic> login({int timeout = 5000}) async {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AliAuthModel {
|
class AliAuthModel {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import '../../../../core/network/api_client.dart';
|
import '../../../../core/network/api_client.dart';
|
||||||
|
import '../../../../core/network/api_config.dart';
|
||||||
import '../../domain/entities/auth_tokens.dart';
|
import '../../domain/entities/auth_tokens.dart';
|
||||||
import '../../domain/entities/user.dart';
|
import '../../domain/entities/user.dart';
|
||||||
|
|
||||||
@ -44,8 +45,9 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
|||||||
@override
|
@override
|
||||||
Future<({User user, AuthTokens tokens, bool isNewUser})> tokenLogin(
|
Future<({User user, AuthTokens tokens, bool isNewUser})> tokenLogin(
|
||||||
String token) async {
|
String token) async {
|
||||||
|
// 一键授权登录使用 HTTPS 域名(阿里云号码认证要求)
|
||||||
final data = await _apiClient.post(
|
final data = await _apiClient.post(
|
||||||
'/auth/phone-login/',
|
'${ApiConfig.fullAuthBaseUrl}/auth/phone-login/',
|
||||||
data: {'token': token},
|
data: {'token': token},
|
||||||
);
|
);
|
||||||
return _parseLoginResponse(data as Map<String, dynamic>);
|
return _parseLoginResponse(data as Map<String, dynamic>);
|
||||||
|
|||||||
4
airhub_app/packages/ali_auth/analysis_options.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
8
airhub_app/packages/ali_auth/android/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
*.iml
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/libraries
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
||||||
95
airhub_app/packages/ali_auth/android/build-clone.gradle
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
group 'com.sean.rao.ali_auth'
|
||||||
|
version '1.3.1'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
// google()
|
||||||
|
// jcenter()
|
||||||
|
// JitPack 远程仓库:https://jitpack.io
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url 'https://download.flutter.io'}
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.allprojects {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
// google()
|
||||||
|
// jcenter()
|
||||||
|
// JitPack 远程仓库:https://jitpack.io
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
maven { url 'https://download.flutter.io'}
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
if (project.android.hasProperty("namespace")) {
|
||||||
|
namespace = "com.sean.rao.ali_auth"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileSdkVersion 34
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
}
|
||||||
|
|
||||||
|
aaptOptions {
|
||||||
|
noCompress "mov" //表示不让aapt压缩的文件后缀
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
debuggable false
|
||||||
|
// minifyEnabled true
|
||||||
|
proguardFile file('proguard-rules.pro')
|
||||||
|
zipAlignEnabled false
|
||||||
|
multiDexEnabled true
|
||||||
|
}
|
||||||
|
|
||||||
|
debug {
|
||||||
|
// minifyEnabled false
|
||||||
|
zipAlignEnabled false
|
||||||
|
multiDexEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "androidx.appcompat:appcompat:1.7.1"
|
||||||
|
|
||||||
|
// 兼容安卓版本的fastjson库
|
||||||
|
implementation 'com.alibaba.fastjson2:fastjson2:2.0.51.android5'
|
||||||
|
// implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
// implementation 'com.alibaba:fastjson:1.2.83'
|
||||||
|
|
||||||
|
implementation files("libs/auth_number_product-${authLibVersion}-release.aar")
|
||||||
|
implementation files("libs/logger-${loggerVersion}-release.aar")
|
||||||
|
implementation files("libs/main-${mainVersion}-release.aar")
|
||||||
|
|
||||||
|
// 吐司框架:https://github.com/getActivity/Toaster
|
||||||
|
implementation 'com.github.getActivity:Toaster:12.2'
|
||||||
|
|
||||||
|
// uc的crash收集库,客户可自行选择是否需要集成
|
||||||
|
// implementation 'com.ucweb.wpk:crashsdk:3.2.2.2'
|
||||||
|
}
|
||||||
|
}
|
||||||
107
airhub_app/packages/ali_auth/android/build.gradle
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
group 'com.sean.rao.ali_auth'
|
||||||
|
version '1.3.7'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
// google()
|
||||||
|
// jcenter()
|
||||||
|
maven { url 'https://dl.bintray.com/jetbrains/anko'}
|
||||||
|
maven { url 'https://download.flutter.io'}
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义一个方法, 用于获取当前moudle的dir
|
||||||
|
def getCurrentProjectDir() {
|
||||||
|
String result = ""
|
||||||
|
rootProject.allprojects { project ->
|
||||||
|
if (project.properties.get("identityPath").toString() == ":ali_auth") { // 这里是flutter的约定, 插件的module名是插件名, :是gradle的约定. project前加:
|
||||||
|
result = project.properties.get("projectDir").toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
rootProject.allprojects {
|
||||||
|
def dir = getCurrentProjectDir()
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
// google()
|
||||||
|
// jcenter()
|
||||||
|
maven { url 'https://dl.bintray.com/jetbrains/anko'}
|
||||||
|
maven { url 'https://download.flutter.io'}
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||||
|
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||||
|
|
||||||
|
// 一键登录本地依赖
|
||||||
|
flatDir {
|
||||||
|
dirs project(':ali_auth').file('libs')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
if (project.android.hasProperty("namespace")) {
|
||||||
|
namespace = "com.sean.rao.ali_auth"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileSdkVersion 35
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
}
|
||||||
|
|
||||||
|
aaptOptions {
|
||||||
|
noCompress "mov" //表示不让aapt压缩的文件后缀
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
debuggable false
|
||||||
|
// minifyEnabled true
|
||||||
|
proguardFile file('proguard-rules.pro')
|
||||||
|
zipAlignEnabled false
|
||||||
|
multiDexEnabled true
|
||||||
|
}
|
||||||
|
|
||||||
|
debug {
|
||||||
|
// minifyEnabled false
|
||||||
|
zipAlignEnabled false
|
||||||
|
multiDexEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "androidx.appcompat:appcompat:1.3.0"
|
||||||
|
|
||||||
|
// 兼容安卓版本的fastjson库
|
||||||
|
implementation "com.alibaba.fastjson2:fastjson2:2.0.51.android5"
|
||||||
|
// implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
// implementation 'com.alibaba:fastjson:1.2.83'
|
||||||
|
|
||||||
|
implementation(name: "auth_number_product-${authLibVersion}-release", ext:'aar')
|
||||||
|
implementation(name: "logger-${loggerVersion}-release", ext:'aar')
|
||||||
|
implementation(name: "main-${mainVersion}-release", ext:'aar')
|
||||||
|
|
||||||
|
// 吐司框架:https://github.com/getActivity/Toaster
|
||||||
|
// implementation 'com.github.getActivity:Toaster:12.2'
|
||||||
|
|
||||||
|
// uc的crash收集库,客户可自行选择是否需要集成
|
||||||
|
// implementation 'com.ucweb.wpk:crashsdk:3.2.2.2'
|
||||||
|
}
|
||||||
21
airhub_app/packages/ali_auth/android/gradle.properties
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Project-wide Gradle settings.
|
||||||
|
|
||||||
|
# IDE (e.g. Android Studio) users:
|
||||||
|
# Gradle settings configured through the IDE *will override*
|
||||||
|
# any settings specified in this file.
|
||||||
|
|
||||||
|
# For more details on how to configure your build environment visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||||
|
|
||||||
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
# org.gradle.parallel=true
|
||||||
|
android.injected.testOnly=false
|
||||||
|
|
||||||
|
authLibVersion=2.14.19
|
||||||
|
loggerVersion=2.2.2
|
||||||
|
mainVersion=2.2.3
|
||||||
3
airhub_app/packages/ali_auth/android/libs/deploy.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mvn deploy:deploy-file -Dfile=sdk.aar -Durl="file://." -DgroupId="com.pgyer" -DartifactId="sdk" -Dversion="3.0.9"
|
||||||
|
|
||||||
|
mvn deploy:deploy-file -Dfile=sdk.aar -Durl="file://." -DgroupId="com.mobile.auth" -DartifactId="auth-number-product" -Dversion="2.14.14"
|
||||||
BIN
airhub_app/packages/ali_auth/android/libs/main-2.2.3-release.aar
Normal file
10
airhub_app/packages/ali_auth/android/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# 感谢 ZengJo的贡献
|
||||||
|
-keep class android.app.ActivityThread {*;}
|
||||||
|
-keep class android.os.SystemProperties {*;}
|
||||||
|
|
||||||
|
-keep class com.mobile.auth.** { *; }
|
||||||
|
-keep class com.alibaba.sdk.android.* { *; }
|
||||||
|
-keep class com.alicom.* { *; }
|
||||||
|
-keep class com.taobao.* { *; }
|
||||||
|
-keep class androidx.appcompat.** { *; }
|
||||||
|
-keep class com.cmic.** { *; }
|
||||||
1
airhub_app/packages/ali_auth/android/settings.gradle
Normal file
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'ali_auth'
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
package="com.sean.rao.ali_auth">
|
||||||
|
|
||||||
|
<!--允许访问网络状态的权限-->
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<!--允许修改网络状态的权限-->
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
|
||||||
|
<!--允许修改 WIFI 状态的权限。-->
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
|
||||||
|
<!--允许访问 WIFI 状态的权限-->
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||||
|
|
||||||
|
<!-- 跳转原生调用flutter时页面的样式 -->
|
||||||
|
<application
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
tools:targetApi="m">
|
||||||
|
<activity
|
||||||
|
android:name="io.flutter.embedding.android.FlutterActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar"
|
||||||
|
android:windowSoftInputMode="adjustResize"
|
||||||
|
android:usesCleartextTraffic="true"/>
|
||||||
|
|
||||||
|
<!--协议页面webview-->
|
||||||
|
<activity
|
||||||
|
android:name="com.mobile.auth.gatewayauth.activity.AuthWebVeiwActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
tools:replace="android:theme"
|
||||||
|
android:exported="false"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:screenOrientation="behind"
|
||||||
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
|
||||||
|
|
||||||
|
<!--联通电信授权页-->
|
||||||
|
<activity
|
||||||
|
android:name="com.mobile.auth.gatewayauth.LoginAuthActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
tools:replace="android:configChanges"
|
||||||
|
android:exported="false"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:screenOrientation="behind"
|
||||||
|
android:theme="@style/authsdk_activity_dialog"/>
|
||||||
|
|
||||||
|
<!--移动授权页-->
|
||||||
|
<activity
|
||||||
|
android:name="com.cmic.sso.sdk.activity.LoginAuthActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
tools:replace="android:configChanges"
|
||||||
|
android:exported="false"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:screenOrientation="behind"
|
||||||
|
android:theme="@style/authsdk_activity_dialog" />
|
||||||
|
|
||||||
|
<!--二次弹窗-->
|
||||||
|
<activity
|
||||||
|
android:name="com.mobile.auth.gatewayauth.PrivacyDialogActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
tools:replace="android:configChanges"
|
||||||
|
android:exported="false"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:screenOrientation="behind"
|
||||||
|
android:theme="@style/authsdk_activity_dialog"/>
|
||||||
|
|
||||||
|
<!--适配华为刘海屏-->
|
||||||
|
<meta-data
|
||||||
|
android:name="android.notch_support"
|
||||||
|
android:value="true"/>
|
||||||
|
<!--适配小米刘海屏-->
|
||||||
|
<meta-data
|
||||||
|
android:name="notch.config"
|
||||||
|
android:value="portrait|landscape" />
|
||||||
|
|
||||||
|
</application>
|
||||||
|
</manifest>
|
||||||
@ -0,0 +1,306 @@
|
|||||||
|
package com.sean.rao.ali_auth;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.Network;
|
||||||
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
import android.net.NetworkRequest;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import io.flutter.embedding.android.FlutterActivity;
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine;
|
||||||
|
import io.flutter.embedding.engine.FlutterEngineCache;
|
||||||
|
import io.flutter.embedding.engine.dart.DartExecutor;
|
||||||
|
import io.flutter.embedding.engine.plugins.FlutterPlugin;
|
||||||
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
|
||||||
|
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
import io.flutter.plugin.common.MethodCall;
|
||||||
|
import io.flutter.plugin.common.MethodChannel;
|
||||||
|
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
|
||||||
|
import io.flutter.plugin.common.MethodChannel.Result;
|
||||||
|
|
||||||
|
import com.sean.rao.ali_auth.common.LoginParams;
|
||||||
|
import com.sean.rao.ali_auth.login.OneKeyLoginPublic;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
/** AliAuthPlugin */
|
||||||
|
public class AliAuthPlugin extends FlutterActivity implements FlutterPlugin, ActivityAware, MethodCallHandler, EventChannel.StreamHandler {
|
||||||
|
private static final String TAG = "ali_auth 一键登录插件";
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private Activity mActivity;
|
||||||
|
/// The MethodChannel that will the communication between Flutter and native Android
|
||||||
|
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||||
|
/// when the Flutter Engine is detached from the Activity
|
||||||
|
private MethodChannel channel;
|
||||||
|
|
||||||
|
private FlutterEngine flutterEngine;
|
||||||
|
|
||||||
|
private FlutterEngineCache flutterEngineCache;
|
||||||
|
|
||||||
|
public static EventChannel.EventSink _events;
|
||||||
|
|
||||||
|
private static final String METHOD_CHANNEL = "ali_auth";
|
||||||
|
private static final String EVENT_CHANNEL = "ali_auth/event";
|
||||||
|
|
||||||
|
private ConnectivityManager.NetworkCallback callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延时登录
|
||||||
|
*/
|
||||||
|
private OneKeyLoginPublic oneKeyLoginPublic;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
|
||||||
|
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), METHOD_CHANNEL);
|
||||||
|
|
||||||
|
// 原生通讯
|
||||||
|
EventChannel eventChannel = new EventChannel(flutterPluginBinding.getBinaryMessenger(), EVENT_CHANNEL);
|
||||||
|
eventChannel.setStreamHandler(this);
|
||||||
|
// // Activity
|
||||||
|
// flutterView.getLookupKeyForAsset("images/ic_launcher.png");
|
||||||
|
// // Fragment
|
||||||
|
// (FlutterView) getView().getLookupKeyForAsset("images/ic_launcher.png");
|
||||||
|
// // 通用
|
||||||
|
// FlutterMain.getLookupKeyForAsset("images/ic_launcher.png");
|
||||||
|
|
||||||
|
// 创建flutter发动机
|
||||||
|
flutterEngineCache = FlutterEngineCache.getInstance();
|
||||||
|
channel.setMethodCallHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
|
||||||
|
switch (call.method){
|
||||||
|
case "getPlatformVersion":
|
||||||
|
result.success("当前Android信息:" + android.os.Build.VERSION.RELEASE);
|
||||||
|
break;
|
||||||
|
case "getCurrentCarrierName":
|
||||||
|
// CMCC(移动)、CUCC(联通)、CTCC(电信)
|
||||||
|
String carrierName = "获取失败";
|
||||||
|
if (oneKeyLoginPublic == null) {
|
||||||
|
PhoneNumberAuthHelper phoneNumberAuthHelper = PhoneNumberAuthHelper.getInstance(mActivity, null);
|
||||||
|
carrierName = phoneNumberAuthHelper.getCurrentCarrierName();
|
||||||
|
} else {
|
||||||
|
carrierName = oneKeyLoginPublic.getCurrentCarrierName();
|
||||||
|
}
|
||||||
|
if (carrierName.contains("CMCC")) {
|
||||||
|
carrierName = "中国移动";
|
||||||
|
} else if (carrierName.contains("CUCC")) {
|
||||||
|
carrierName = "中国联通";
|
||||||
|
} else if (carrierName.contains("CTCC")) {
|
||||||
|
carrierName = "中国电信";
|
||||||
|
}
|
||||||
|
result.success(carrierName);
|
||||||
|
break;
|
||||||
|
case "initSdk":
|
||||||
|
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(call.arguments));
|
||||||
|
if (_events == null) {
|
||||||
|
result.error("500001", "请先对插件进行监听!", null);
|
||||||
|
} else {
|
||||||
|
boolean isDelay = jsonObject.getBoolean("isDelay");
|
||||||
|
/// 判断是否初始化过或者是否是同步登录,如果是将进行再次初始化
|
||||||
|
if (oneKeyLoginPublic == null || !isDelay) {
|
||||||
|
try {
|
||||||
|
oneKeyLoginPublic = new OneKeyLoginPublic(mActivity, _events, call.arguments);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "initSdk 初始化异常: " + e.getMessage(), e);
|
||||||
|
_events.success(UtilTool.resultFormatData("500000", "SDK初始化异常: " + e.getMessage(), ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.success(null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "login":
|
||||||
|
if (oneKeyLoginPublic != null) {
|
||||||
|
oneKeyLoginPublic.startLogin(LoginParams.jsonObject.getIntValue("timeout", 5000));
|
||||||
|
} else {
|
||||||
|
_events.success(UtilTool.resultFormatData("500003", null, ""));
|
||||||
|
}
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "checkEnvAvailable":
|
||||||
|
oneKeyLoginPublic.checkEnvAvailable(2);
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "queryCheckBoxIsChecked":
|
||||||
|
boolean status = oneKeyLoginPublic.queryCheckBoxIsChecked();
|
||||||
|
result.success(status);
|
||||||
|
break;
|
||||||
|
case "setCheckboxIsChecked":
|
||||||
|
boolean checked = oneKeyLoginPublic.setCheckBoxIsChecked();
|
||||||
|
result.success(checked);
|
||||||
|
break;
|
||||||
|
case "checkCellularDataEnable":
|
||||||
|
isNetEnabled(mContext, result);
|
||||||
|
break;
|
||||||
|
case "quitPage":
|
||||||
|
oneKeyLoginPublic.quitPage();
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "hideLoading":
|
||||||
|
oneKeyLoginPublic.hideLoading();
|
||||||
|
result.success(null);
|
||||||
|
break;
|
||||||
|
case "openPage":
|
||||||
|
if (flutterEngine == null) {
|
||||||
|
flutterEngine = new FlutterEngine(mContext);
|
||||||
|
}
|
||||||
|
//指定想要跳转的flutter页面 这里要和下图对应上 记住他
|
||||||
|
flutterEngine.getNavigationChannel().setInitialRoute(call.argument("pageRoute"));
|
||||||
|
flutterEngine.getDartExecutor().executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());
|
||||||
|
//这里做一个缓存 可以在适当的地方执行他 比如MyApp里 或者未跳转flutterr之前 在flutter页面执行前预加载
|
||||||
|
//缓存可以缓存好多个 以不同的的id区分
|
||||||
|
flutterEngineCache.put("default_engine_id", flutterEngine);
|
||||||
|
//上面的代码一般在执行跳转操作之前调用 这样可以预加载页面 是的跳转的时候速度加快
|
||||||
|
//跳转页面
|
||||||
|
mActivity.startActivity(FlutterActivity.withCachedEngine("default_engine_id").build(mContext));
|
||||||
|
result.success("调用成功!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.notImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListen(Object o, EventChannel.EventSink eventSink) {
|
||||||
|
Log.d(TAG, "listen 初始化完毕!");
|
||||||
|
String version = PhoneNumberAuthHelper.getVersion();
|
||||||
|
eventSink.success(UtilTool.resultFormatData("500004", String.format("插件启动监听成功, 当前SDK版本: %s", version), ""));
|
||||||
|
if( _events == null ){
|
||||||
|
_events = eventSink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCancel(Object o) {
|
||||||
|
if( _events != null){
|
||||||
|
_events = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
|
||||||
|
channel.setMethodCallHandler(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
|
||||||
|
mActivity = binding.getActivity();
|
||||||
|
mContext = mActivity.getBaseContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromActivityForConfigChanges() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDetachedFromActivity() {
|
||||||
|
if( _events != null){
|
||||||
|
_events.endOfStream();
|
||||||
|
}
|
||||||
|
mActivity = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断移动网络是否开启
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public void isNetEnabled(Context context, @NonNull Result result) {
|
||||||
|
JSONObject resultObject = new JSONObject();
|
||||||
|
resultObject.put("code", 0);
|
||||||
|
resultObject.put("msg", "未检测到网络!");
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||||
|
// callback = new ConnectivityManager.NetworkCallback() {
|
||||||
|
// // 可用网络接入
|
||||||
|
// public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
|
||||||
|
// // 一般在此处获取网络类型然后判断网络类型,就知道时哪个网络可以用connected
|
||||||
|
// System.out.println(network);
|
||||||
|
// System.out.println(networkCapabilities);
|
||||||
|
// }
|
||||||
|
// // 网络断开
|
||||||
|
// public void onLost(Network network) {
|
||||||
|
// System.out.println(network);
|
||||||
|
// // 如果通过ConnectivityManager#getActiveNetwork()返回null,表示当前已经没有其他可用网络了。
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// registerNetworkCallback(context);
|
||||||
|
|
||||||
|
Network network =cm.getActiveNetwork();
|
||||||
|
if(network!=null){
|
||||||
|
NetworkCapabilities nc=cm.getNetworkCapabilities(network);
|
||||||
|
if(nc!=null){
|
||||||
|
resultObject.put("code", 1);
|
||||||
|
if(nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)){ // WIFI
|
||||||
|
resultObject.put("msg", "WIFI网络已开启");
|
||||||
|
}else if(nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)){ // 移动数据
|
||||||
|
resultObject.put("msg", "蜂窝网络已开启");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NetworkInfo mWiFiNetworkInfo = cm.getActiveNetworkInfo();
|
||||||
|
if (mWiFiNetworkInfo != null) {
|
||||||
|
resultObject.put("code", 1);
|
||||||
|
if (mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) { // WIFI
|
||||||
|
resultObject.put("msg", "WIFI网络已开启");
|
||||||
|
} else if (mWiFiNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { // 移动数据
|
||||||
|
resultObject.put("msg", "蜂窝网络已开启");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.success(resultObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册回调
|
||||||
|
private void registerNetworkCallback(Context context) {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
NetworkRequest.Builder builder = new NetworkRequest.Builder();
|
||||||
|
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||||
|
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
|
||||||
|
cm.registerNetworkCallback(builder.build(), callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注销回调
|
||||||
|
private void unregisterNetworkCallback(Context context) {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
cm.unregisterNetworkCallback(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断移动网络是否连接成功
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isNetContected(Context context) {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
|
||||||
|
if (info != null && info.isConnected()) {
|
||||||
|
Log.i(TAG, "移动网络连接成功");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Log.i(TAG, "移动网络连接失败");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.sean.rao.ali_auth.auth;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.webkit.WebSettings;
|
||||||
|
import android.webkit.WebView;
|
||||||
|
import android.widget.Toolbar;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.Constant;
|
||||||
|
import com.sean.rao.ali_auth.R;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: NumberAuthSDK_Standard_Android
|
||||||
|
* @Package: com.aliqin.mytel.auth
|
||||||
|
* @ClassName: CustomWebView
|
||||||
|
* @Description: 自定义协议展示页
|
||||||
|
* @Author: liuqi
|
||||||
|
* @CreateDate: 2021/3/25 4:04 PM
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class CustomWebViewActivity extends Activity {
|
||||||
|
private WebView mWebView;
|
||||||
|
private Toolbar mToolbar;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_custom_web);
|
||||||
|
String mUrl = getIntent().getStringExtra(Constant.PROTOCOL_WEB_VIEW_URL);
|
||||||
|
String mName = getIntent().getStringExtra(Constant.PROTOCOL_WEB_VIEW_NAME);
|
||||||
|
setRequestedOrientation(
|
||||||
|
getIntent().getIntExtra(Constant.PROTOCOL_WEB_VIEW_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT));
|
||||||
|
mWebView = findViewById(R.id.webView);
|
||||||
|
mToolbar = findViewById(R.id.toolbar);
|
||||||
|
|
||||||
|
// mToolbar.setSubtitle(mName);
|
||||||
|
initWebView();
|
||||||
|
mWebView.loadUrl(mUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
|
private void initWebView() {
|
||||||
|
WebSettings wvSettings = mWebView.getSettings();
|
||||||
|
// 是否阻止网络图像
|
||||||
|
wvSettings.setBlockNetworkImage(false);
|
||||||
|
// 是否阻止网络请求
|
||||||
|
wvSettings.setBlockNetworkLoads(false);
|
||||||
|
// 是否加载JS
|
||||||
|
wvSettings.setJavaScriptEnabled(true);
|
||||||
|
wvSettings.setJavaScriptCanOpenWindowsAutomatically(true);
|
||||||
|
//覆盖方式启动缓存
|
||||||
|
wvSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
|
||||||
|
// 使用广泛视窗
|
||||||
|
wvSettings.setUseWideViewPort(true);
|
||||||
|
wvSettings.setLoadWithOverviewMode(true);
|
||||||
|
wvSettings.setDomStorageEnabled(true);
|
||||||
|
//是否支持缩放
|
||||||
|
wvSettings.setBuiltInZoomControls(false);
|
||||||
|
wvSettings.setSupportZoom(false);
|
||||||
|
//不显示缩放按钮
|
||||||
|
wvSettings.setDisplayZoomControls(false);
|
||||||
|
wvSettings.setAllowFileAccess(true);
|
||||||
|
wvSettings.setDatabaseEnabled(true);
|
||||||
|
//缓存相关
|
||||||
|
// wvSettings.setAppCacheEnabled(true);
|
||||||
|
wvSettings.setDomStorageEnabled(true);
|
||||||
|
wvSettings.setDatabaseEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
package com.sean.rao.ali_auth.auth;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import com.mobile.auth.gatewayauth.PreLoginResultListener;
|
||||||
|
import com.mobile.auth.gatewayauth.ResultCode;
|
||||||
|
import com.mobile.auth.gatewayauth.TokenResultListener;
|
||||||
|
import com.mobile.auth.gatewayauth.model.TokenRet;
|
||||||
|
import com.sean.rao.ali_auth.utils.ExecutorManager;
|
||||||
|
|
||||||
|
public class NumberAuthActivity extends Activity {
|
||||||
|
private static final String TAG = NumberAuthActivity.class.getSimpleName();
|
||||||
|
private PhoneNumberAuthHelper mAuthHelper;
|
||||||
|
private TokenResultListener mVerifyListener;
|
||||||
|
private Button mAuthButton;
|
||||||
|
private EditText mNumberEt;
|
||||||
|
private String phoneNumber;
|
||||||
|
private ProgressDialog mProgressDialog;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
// setContentView(R.layout.activity_auth);
|
||||||
|
// mAuthButton = findViewById(R.id.auth_btn);
|
||||||
|
// mNumberEt = findViewById(R.id.et_number);
|
||||||
|
mAuthButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
phoneNumber = mNumberEt.getText().toString();
|
||||||
|
//判断手机号是否合法
|
||||||
|
if (!TextUtils.isEmpty(phoneNumber)) {
|
||||||
|
showLoadingDialog("正在进行本机号码校验");
|
||||||
|
numberAuth(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sdkInit();
|
||||||
|
accelerateVerify(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sdkInit() {
|
||||||
|
mVerifyListener = new TokenResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onTokenSuccess(String s) {
|
||||||
|
Log.i(TAG, "获取token成功:" + s);
|
||||||
|
try {
|
||||||
|
TokenRet pTokenRet = TokenRet.fromJson(s);
|
||||||
|
if (ResultCode.CODE_SUCCESS.equals(pTokenRet.getCode()) && !TextUtils.isEmpty(pTokenRet.getToken())) {
|
||||||
|
getResultWithToken(pTokenRet.getToken(), phoneNumber);
|
||||||
|
}
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTokenFailed(final String s) {
|
||||||
|
Log.i(TAG, "获取token失败:" + s);
|
||||||
|
NumberAuthActivity.this.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
hideLoadingDialog();
|
||||||
|
setResult(2);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mAuthHelper = PhoneNumberAuthHelper.getInstance(getApplicationContext(), mVerifyListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加速校验
|
||||||
|
* 进入输入手机号页面调用此接口,用户输入完手机号点击确定可以更快的获取token
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void accelerateVerify(int timeout) {
|
||||||
|
mAuthHelper.accelerateVerify(timeout, new PreLoginResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onTokenSuccess(String vendor) {
|
||||||
|
//成功时返回运营商简称
|
||||||
|
Log.i(TAG, "accelerateVerify:" + vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTokenFailed(String vendor, String errorMsg) {
|
||||||
|
Log.e(TAG, "accelerateVerify:" + vendor + ", " + errorMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void numberAuth(int timeout) {
|
||||||
|
mAuthHelper.setAuthListener(mVerifyListener);
|
||||||
|
mAuthHelper.getVerifyToken(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getResultWithToken(final String token, final String phoneNumber) {
|
||||||
|
ExecutorManager.run(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// final String result = verifyNumber(token, phoneNumber);
|
||||||
|
NumberAuthActivity.this.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
hideLoadingDialog();
|
||||||
|
Intent pIntent = new Intent();
|
||||||
|
pIntent.putExtra("result", phoneNumber);
|
||||||
|
setResult(1, pIntent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showLoadingDialog(String hint) {
|
||||||
|
if (mProgressDialog == null) {
|
||||||
|
mProgressDialog = new ProgressDialog(this);
|
||||||
|
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||||
|
}
|
||||||
|
mProgressDialog.setMessage(hint);
|
||||||
|
mProgressDialog.setCancelable(true);
|
||||||
|
mProgressDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideLoadingDialog() {
|
||||||
|
if (mProgressDialog != null) {
|
||||||
|
mProgressDialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,213 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.LruCache;
|
||||||
|
|
||||||
|
import com.nirvana.tools.core.CryptUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Package: com.aliqin.mytel
|
||||||
|
* @ClassName: CacheManage
|
||||||
|
* @Description: 类作用描述
|
||||||
|
* @Author: liuqi
|
||||||
|
* @CreateDate: 2021/5/13 9:55 AM
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class CacheManage {
|
||||||
|
Context context;
|
||||||
|
private LruCache<String, Bitmap> mBitmapLruCache = null;
|
||||||
|
private ConcurrentHashMap<String, String> mFilePathCache = null;
|
||||||
|
private final static String CACHE_FILE_DIR = "ALSDK_FILE_CACHE";
|
||||||
|
private final static String CACHE_COVER_DIR = "ALSDK_COVER_CACHE";
|
||||||
|
|
||||||
|
public CacheManage(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
final File dir = new File(context.getCacheDir(), CACHE_FILE_DIR);
|
||||||
|
if (dir.exists()) {
|
||||||
|
mFilePathCache = new ConcurrentHashMap<String, String>();
|
||||||
|
File[] listFiles = dir.listFiles();
|
||||||
|
if (null != listFiles && listFiles.length > 0) {
|
||||||
|
for (File file : listFiles) {
|
||||||
|
String fileName = file.getName();
|
||||||
|
String key = fileName.substring(0, fileName.lastIndexOf("."));
|
||||||
|
mFilePathCache.put(key, file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建缓存文件
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param ext 文件后缀
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public File createCacheFile(String url, String ext) {
|
||||||
|
final File dir = new File(context.getCacheDir(), CACHE_FILE_DIR);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
String key = url;
|
||||||
|
try {
|
||||||
|
key = CryptUtil.md5Hex(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
key = url;
|
||||||
|
}
|
||||||
|
return new File(dir, key + ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取bitma内存缓存
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public LruCache<String, Bitmap> getBitmapLruCache() {
|
||||||
|
if (mBitmapLruCache == null) {
|
||||||
|
long mTotalSize = Runtime.getRuntime().totalMemory();
|
||||||
|
mBitmapLruCache = new LruCache<>((int)(mTotalSize / 5));
|
||||||
|
}
|
||||||
|
return mBitmapLruCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取文件缓存
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getCacheFilePath(String url) {
|
||||||
|
String key = url;
|
||||||
|
try {
|
||||||
|
key = CryptUtil.md5Hex(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
key = url;
|
||||||
|
}
|
||||||
|
if (mFilePathCache == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return mFilePathCache.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存bitmap到内存
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param bitmap
|
||||||
|
*/
|
||||||
|
public void cacheBitmap(String url, Bitmap bitmap) {
|
||||||
|
String key = url;
|
||||||
|
try {
|
||||||
|
key = CryptUtil.md5Hex(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
key = url;
|
||||||
|
}
|
||||||
|
checkAndCreateBitmapCache();
|
||||||
|
mBitmapLruCache.put(key, bitmap);
|
||||||
|
SaveImageDisk(bitmap, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取内存缓存的bitmap
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Bitmap getBitmap(String url) {
|
||||||
|
String key = url;
|
||||||
|
try {
|
||||||
|
key = CryptUtil.md5Hex(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
key = url;
|
||||||
|
}
|
||||||
|
if (mBitmapLruCache == null) {
|
||||||
|
return getBitmapFromDisk(key + ".jpg");
|
||||||
|
} else {
|
||||||
|
return mBitmapLruCache.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查和创建内存缓存
|
||||||
|
*/
|
||||||
|
public void checkAndCreateBitmapCache() {
|
||||||
|
if (mBitmapLruCache == null) {
|
||||||
|
long mTotalSize = Runtime.getRuntime().totalMemory();
|
||||||
|
mBitmapLruCache = new LruCache<>((int)(mTotalSize / 5));
|
||||||
|
final File dir = new File(context.getCacheDir(), CACHE_COVER_DIR);
|
||||||
|
if (dir.exists()) {
|
||||||
|
File[] listFiles = dir.listFiles();
|
||||||
|
if (null != listFiles && listFiles.length > 0) {
|
||||||
|
for (File file : listFiles) {
|
||||||
|
String fileName = file.getName();
|
||||||
|
fileName = fileName.substring(0, fileName.lastIndexOf("."));
|
||||||
|
String key = fileName;
|
||||||
|
mBitmapLruCache.put(key, getBitmapFromDisk(file.getAbsolutePath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存图片到硬盘
|
||||||
|
* @param image
|
||||||
|
* @param url
|
||||||
|
*/
|
||||||
|
public void SaveImageDisk(Bitmap image, String url) {
|
||||||
|
final File dir = new File(context.getCacheDir(), CACHE_COVER_DIR);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdirs();
|
||||||
|
}
|
||||||
|
String key = url;
|
||||||
|
try {
|
||||||
|
key = CryptUtil.md5Hex(key);
|
||||||
|
} catch (Exception e) {
|
||||||
|
key = url;
|
||||||
|
}
|
||||||
|
File imageDir = new File(dir, key + ".jpg");
|
||||||
|
FileOutputStream fos = null;
|
||||||
|
try {
|
||||||
|
fos = new FileOutputStream(imageDir);
|
||||||
|
image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
|
||||||
|
fos.flush();
|
||||||
|
fos.close();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e("CacheManage", "SaveImage:e" + e.getMessage());
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("CacheManage", "SaveImage:e" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从硬盘读取文件
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Bitmap getBitmapFromDisk(String path) {
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
FileInputStream fis = null;
|
||||||
|
File f = new File(path);
|
||||||
|
if (!f.exists()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fis = new FileInputStream(path);
|
||||||
|
bitmap = BitmapFactory.decodeStream(fis);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
Log.e("CacheManage", "getBitmap:e" + e.getMessage());
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
|
||||||
|
public class Constant {
|
||||||
|
public static final String[] TYPES = {
|
||||||
|
"全屏(竖屏)", "全屏(横屏)", "弹窗(竖屏)",
|
||||||
|
"弹窗(横屏)", "底部弹窗", "自定义View", "自定义View(Xml)","自定义Gif背景","自定义视频背景(mov,mp4)","自定义图片背景"
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 全屏(竖屏)
|
||||||
|
*/
|
||||||
|
public static final int FULL_PORT = 0;
|
||||||
|
/**
|
||||||
|
* 全屏(横屏)
|
||||||
|
*/
|
||||||
|
public static final int FULL_LAND = 1;
|
||||||
|
/**
|
||||||
|
* 弹窗(竖屏)
|
||||||
|
*/
|
||||||
|
public static final int DIALOG_PORT = 2;
|
||||||
|
/**
|
||||||
|
* "弹窗(横屏)
|
||||||
|
*/
|
||||||
|
public static final int DIALOG_LAND = 3;
|
||||||
|
/**
|
||||||
|
* 底部弹窗
|
||||||
|
*/
|
||||||
|
public static final int DIALOG_BOTTOM = 4;
|
||||||
|
/**
|
||||||
|
* 自定义View
|
||||||
|
*/
|
||||||
|
public static final int CUSTOM_VIEW = 5;
|
||||||
|
/**
|
||||||
|
* 自定义View(Xml)
|
||||||
|
*/
|
||||||
|
public static final int CUSTOM_XML = 6;
|
||||||
|
/**
|
||||||
|
* 自定义背景GIF
|
||||||
|
*/
|
||||||
|
public static final int CUSTOM_GIF = 7;
|
||||||
|
/**
|
||||||
|
* 自定义背景视频
|
||||||
|
*/
|
||||||
|
public static final int CUSTOM_MOV = 8;
|
||||||
|
/**
|
||||||
|
* 自定义背景图片
|
||||||
|
*/
|
||||||
|
public static final int CUSTOM_PIC = 9;
|
||||||
|
|
||||||
|
public static final String THEME_KEY = "theme";
|
||||||
|
|
||||||
|
public static final String LOGIN_TYPE = "login_type";
|
||||||
|
public static final int LOGIN = 1;
|
||||||
|
public static final int LOGIN_DELAY = 2;
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONException;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mobile.auth.gatewayauth.AuthUIConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.AuthUIControlClickListener;
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import com.mobile.auth.gatewayauth.ResultCode;
|
||||||
|
import com.sean.rao.ali_auth.utils.StatusAll;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: android
|
||||||
|
* @Package: com.sean.rao.ali_auth.common
|
||||||
|
* @ClassName: CUstomAuthUIControlClickListener
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 5/12/22 5:26 PM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 5/12/22 5:26 PM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class CustomAuthUIControlClickListener extends LoginParams implements AuthUIControlClickListener {
|
||||||
|
private final String TAG = "CustomAuth: ";
|
||||||
|
|
||||||
|
public CustomAuthUIControlClickListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(String code, Context context, String jsonString) {
|
||||||
|
JSONObject jsonDataObj = new JSONObject();
|
||||||
|
if(!TextUtils.isEmpty(jsonString)) {
|
||||||
|
jsonDataObj = JSONObject.parseObject(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
//点击授权页默认样式的返回按钮
|
||||||
|
case ResultCode.CODE_ERROR_USER_CANCEL:
|
||||||
|
Log.e(TAG, "点击了授权页默认返回按钮");
|
||||||
|
break;
|
||||||
|
//点击授权页默认样式的切换其他登录方式 会关闭授权页
|
||||||
|
//如果不希望关闭授权页那就setSwitchAccHidden(true)隐藏默认的 通过自定义view添加自己的
|
||||||
|
case ResultCode.CODE_ERROR_USER_SWITCH:
|
||||||
|
Log.e(TAG, "点击了授权页默认切换其他登录方式");
|
||||||
|
break;
|
||||||
|
//点击一键登录按钮会发出此回调
|
||||||
|
//当协议栏没有勾选时 点击按钮会有默认toast 如果不需要或者希望自定义内容 setLogBtnToastHidden(true)隐藏默认Toast
|
||||||
|
//通过此回调自己设置toast
|
||||||
|
case ResultCode.CODE_ERROR_USER_LOGIN_BTN:
|
||||||
|
break;
|
||||||
|
//checkbox状态改变触发此回调
|
||||||
|
case ResultCode.CODE_ERROR_USER_CHECKBOX:
|
||||||
|
isChecked = jsonDataObj.getBooleanValue("isChecked");
|
||||||
|
Log.e(TAG, "checkbox状态变为" + jsonDataObj.getBooleanValue("isChecked"));
|
||||||
|
jsonDataObj = null;
|
||||||
|
break;
|
||||||
|
//点击协议栏触发此回调
|
||||||
|
case ResultCode.CODE_ERROR_USER_PROTOCOL_CONTROL:
|
||||||
|
Log.e(TAG, "点击协议," + "name: " + jsonDataObj.getString("name") + ", url: " + jsonDataObj.getString("url"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
showResult(code, null, jsonDataObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapShader;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Shader;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
public class CustomRoundedDrawable extends Drawable {
|
||||||
|
|
||||||
|
private final Bitmap mBitmap;
|
||||||
|
private final Paint mPaint;
|
||||||
|
private final RectF mRectF;
|
||||||
|
private final float mRadius;
|
||||||
|
|
||||||
|
public CustomRoundedDrawable(Bitmap bitmap, float radius) {
|
||||||
|
mBitmap = bitmap;
|
||||||
|
mRadius = radius;
|
||||||
|
|
||||||
|
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
|
||||||
|
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
mPaint.setShader(shader);
|
||||||
|
|
||||||
|
mRectF = new RectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(@NonNull Canvas canvas) {
|
||||||
|
mRectF.set(getBounds());
|
||||||
|
// 只对左上角和右上角设置圆角
|
||||||
|
float[] radii = {mRadius, 0, 0, mRadius, 0f, 0f, 0f, 0f};
|
||||||
|
// canvas.drawRoundRect(mRectF, mRadius, mRadius, mPaint);
|
||||||
|
// canvas.drawRoundRect(mRectF, radii, mPaint);
|
||||||
|
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
// paint.setColor(0xFF0000FF);
|
||||||
|
Path path = new Path();
|
||||||
|
path.addRoundRect(mRectF, radii, Path.Direction.CW);
|
||||||
|
|
||||||
|
canvas.drawPath(path, paint); // 绘制具有四个不同圆角的矩形
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
mPaint.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(@Nullable ColorFilter colorFilter) {
|
||||||
|
mPaint.setColorFilter(colorFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return mPaint.getAlpha();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicWidth() {
|
||||||
|
return mBitmap.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicHeight() {
|
||||||
|
return mBitmap.getHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.ProtocolException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static android.os.FileUtils.copy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: android
|
||||||
|
* @Package: com.sean.rao.ali_auth.common
|
||||||
|
* @ClassName: DownloadFile
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 5/1/22 11:01 AM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 5/1/22 11:01 AM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
class DownloadFile {
|
||||||
|
public static InputStream getImageToInputStream(String path) { //连接远程网址
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(path);
|
||||||
|
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
|
||||||
|
conn.setConnectTimeout(5000);
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
if (conn.getResponseCode() == 200) {
|
||||||
|
inputStream = conn.getInputStream();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bitmap getImageToBitmap(String path) { //连接远程网址
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(path);
|
||||||
|
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
|
||||||
|
conn.setConnectTimeout(5000);
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
if (conn.getResponseCode() == 200) {
|
||||||
|
InputStream inputStream = conn.getInputStream();
|
||||||
|
final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
|
||||||
|
OutputStream outputStream = new BufferedOutputStream(dataStream, 4 * 1024);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
copy(inputStream,outputStream);
|
||||||
|
}
|
||||||
|
outputStream.flush();
|
||||||
|
final byte[] data =dataStream.toByteArray();
|
||||||
|
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mobile.auth.gatewayauth.AuthUIConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import com.mobile.auth.gatewayauth.TokenResultListener;
|
||||||
|
import com.sean.rao.ali_auth.config.BaseUIConfig;
|
||||||
|
import com.sean.rao.ali_auth.utils.StatusAll;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
public class LoginParams {
|
||||||
|
public static Activity mActivity;
|
||||||
|
|
||||||
|
public static Context mContext;
|
||||||
|
|
||||||
|
public static BaseUIConfig mUIConfig;
|
||||||
|
|
||||||
|
public static JSONObject jsonObject;
|
||||||
|
|
||||||
|
public static AuthUIConfig.Builder config;
|
||||||
|
public static boolean sdkAvailable = true;
|
||||||
|
public static EventChannel.EventSink eventSink;
|
||||||
|
public static TokenResultListener mTokenResultListener;
|
||||||
|
public static Boolean isChecked;
|
||||||
|
|
||||||
|
public static PhoneNumberAuthHelper mAuthHelper;
|
||||||
|
|
||||||
|
public void showResult(String code, String message, Object data){
|
||||||
|
if (eventSink != null) {
|
||||||
|
JSONObject result = resultFormatData(code, message, data);
|
||||||
|
result.put("isChecked", isChecked);
|
||||||
|
eventSink.success(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数据封装
|
||||||
|
* @param code
|
||||||
|
* @param msg
|
||||||
|
* @param jsonDataObj
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static JSONObject resultFormatData(String code, @Nullable String msg, @Nullable Object jsonDataObj){
|
||||||
|
JSONObject jsonObj = new JSONObject();
|
||||||
|
jsonObj.put("code", code);
|
||||||
|
jsonObj.put("msg", msg != null && !msg.isEmpty() ? msg : StatusAll.getName(code));
|
||||||
|
jsonObj.put("data", jsonDataObj != null ? jsonDataObj : "");
|
||||||
|
jsonObj.put("isChecked", jsonObject.getBooleanValue("privacyState", false));
|
||||||
|
return jsonObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,207 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: android
|
||||||
|
* @Package: com.sean.rao.ali_auth.common
|
||||||
|
* @ClassName: MediaFileUtil
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 5/1/22 10:33 AM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 5/1/22 10:33 AM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断文件的类型 视频 音频 图片
|
||||||
|
*/
|
||||||
|
public class MediaFileUtil {
|
||||||
|
public static String sFileExtensions;
|
||||||
|
|
||||||
|
// Audio
|
||||||
|
public static final int FILE_TYPE_MP3 = 1;
|
||||||
|
public static final int FILE_TYPE_M4A = 2;
|
||||||
|
public static final int FILE_TYPE_WAV = 3;
|
||||||
|
public static final int FILE_TYPE_AMR = 4;
|
||||||
|
public static final int FILE_TYPE_AWB = 5;
|
||||||
|
public static final int FILE_TYPE_WMA = 6;
|
||||||
|
public static final int FILE_TYPE_OGG = 7;
|
||||||
|
private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
|
||||||
|
private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_OGG;
|
||||||
|
|
||||||
|
// MIDI
|
||||||
|
public static final int FILE_TYPE_MID = 11;
|
||||||
|
public static final int FILE_TYPE_SMF = 12;
|
||||||
|
public static final int FILE_TYPE_IMY = 13;
|
||||||
|
private static final int FIRST_MIDI_FILE_TYPE = FILE_TYPE_MID;
|
||||||
|
private static final int LAST_MIDI_FILE_TYPE = FILE_TYPE_IMY;
|
||||||
|
|
||||||
|
// Video
|
||||||
|
public static final int FILE_TYPE_MP4 = 21;
|
||||||
|
public static final int FILE_TYPE_M4V = 22;
|
||||||
|
public static final int FILE_TYPE_3GPP = 23;
|
||||||
|
public static final int FILE_TYPE_3GPP2 = 24;
|
||||||
|
public static final int FILE_TYPE_WMV = 25;
|
||||||
|
private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
|
||||||
|
private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WMV;
|
||||||
|
|
||||||
|
// Image
|
||||||
|
public static final int FILE_TYPE_JPEG = 31;
|
||||||
|
public static final int FILE_TYPE_GIF = 32;
|
||||||
|
public static final int FILE_TYPE_PNG = 33;
|
||||||
|
public static final int FILE_TYPE_BMP = 34;
|
||||||
|
public static final int FILE_TYPE_WBMP = 35;
|
||||||
|
private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG;
|
||||||
|
private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_WBMP;
|
||||||
|
|
||||||
|
// Playlist
|
||||||
|
public static final int FILE_TYPE_M3U = 41;
|
||||||
|
public static final int FILE_TYPE_PLS = 42;
|
||||||
|
public static final int FILE_TYPE_WPL = 43;
|
||||||
|
private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
|
||||||
|
private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_WPL;
|
||||||
|
|
||||||
|
//静态内部类
|
||||||
|
public static class MediaFileType {
|
||||||
|
|
||||||
|
int fileType;
|
||||||
|
String mimeType;
|
||||||
|
|
||||||
|
MediaFileType(int fileType, String mimeType) {
|
||||||
|
this.fileType = fileType;
|
||||||
|
this.mimeType = mimeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashMap<String, MediaFileType> sFileTypeMap
|
||||||
|
= new HashMap<String, MediaFileType>();
|
||||||
|
private static HashMap<String, Integer> sMimeTypeMap
|
||||||
|
= new HashMap<String, Integer>();
|
||||||
|
static void addFileType(String extension, int fileType, String mimeType) {
|
||||||
|
sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType));
|
||||||
|
sMimeTypeMap.put(mimeType, new Integer(fileType));
|
||||||
|
}
|
||||||
|
static {
|
||||||
|
addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg");
|
||||||
|
addFileType("M4A", FILE_TYPE_M4A, "audio/mp4");
|
||||||
|
addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav");
|
||||||
|
addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
|
||||||
|
addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
|
||||||
|
addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma");
|
||||||
|
addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
|
||||||
|
|
||||||
|
addFileType("MID", FILE_TYPE_MID, "audio/midi");
|
||||||
|
addFileType("XMF", FILE_TYPE_MID, "audio/midi");
|
||||||
|
addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
|
||||||
|
addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
|
||||||
|
addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");
|
||||||
|
|
||||||
|
addFileType("MP4", FILE_TYPE_MP4, "video/mp4");
|
||||||
|
addFileType("M4V", FILE_TYPE_M4V, "video/mp4");
|
||||||
|
addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp");
|
||||||
|
addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp");
|
||||||
|
addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2");
|
||||||
|
addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2");
|
||||||
|
addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv");
|
||||||
|
|
||||||
|
addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg");
|
||||||
|
addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg");
|
||||||
|
addFileType("GIF", FILE_TYPE_GIF, "image/gif");
|
||||||
|
addFileType("PNG", FILE_TYPE_PNG, "image/png");
|
||||||
|
addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp");
|
||||||
|
addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp");
|
||||||
|
|
||||||
|
addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl");
|
||||||
|
addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls");
|
||||||
|
addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl");
|
||||||
|
|
||||||
|
// compute file extensions list for native Media Scanner
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
Iterator<String> iterator = sFileTypeMap.keySet().iterator();
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.append(',');
|
||||||
|
}
|
||||||
|
builder.append(iterator.next());
|
||||||
|
}
|
||||||
|
sFileExtensions = builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String UNKNOWN_STRING = "<unknown>";
|
||||||
|
|
||||||
|
public static boolean isAudioFileType(int fileType) {
|
||||||
|
return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
|
||||||
|
fileType <= LAST_AUDIO_FILE_TYPE) ||
|
||||||
|
(fileType >= FIRST_MIDI_FILE_TYPE &&
|
||||||
|
fileType <= LAST_MIDI_FILE_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isVideoFileType(int fileType) {
|
||||||
|
return (fileType >= FIRST_VIDEO_FILE_TYPE &&
|
||||||
|
fileType <= LAST_VIDEO_FILE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isImageFileType(int fileType) {
|
||||||
|
return (fileType >= FIRST_IMAGE_FILE_TYPE &&
|
||||||
|
fileType <= LAST_IMAGE_FILE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPlayListFileType(int fileType) {
|
||||||
|
return (fileType >= FIRST_PLAYLIST_FILE_TYPE &&
|
||||||
|
fileType <= LAST_PLAYLIST_FILE_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MediaFileType getFileType(String path) {
|
||||||
|
int lastDot = path.lastIndexOf(".");
|
||||||
|
if (lastDot < 0)
|
||||||
|
return null;
|
||||||
|
return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据视频文件路径判断文件类型
|
||||||
|
public static boolean isVideoFileType(String path) {
|
||||||
|
MediaFileType type = getFileType(path);
|
||||||
|
if(null != type) {
|
||||||
|
return isVideoFileType(type.fileType);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据音频文件路径判断文件类型
|
||||||
|
public static boolean isAudioFileType(String path) {
|
||||||
|
MediaFileType type = getFileType(path);
|
||||||
|
if(null != type) {
|
||||||
|
return isAudioFileType(type.fileType);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据mime类型查看文件类型
|
||||||
|
public static int getFileTypeForMimeType(String mimeType) {
|
||||||
|
Integer value = sMimeTypeMap.get(mimeType);
|
||||||
|
return (value == null ? 0 : value.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据图片文件路径判断是否时gif文件类型
|
||||||
|
public static boolean isImageGifFileType(String path) {
|
||||||
|
MediaFileType type = getFileType(path);
|
||||||
|
if(null != type) {
|
||||||
|
return FILE_TYPE_GIF == type.fileType;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据图片文件路径判断文件类型
|
||||||
|
public static boolean isImageFileType(String path) {
|
||||||
|
MediaFileType type = getFileType(path);
|
||||||
|
if(null != type) {
|
||||||
|
return isImageFileType(type.fileType);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,584 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Application;
|
||||||
|
import android.app.Application.ActivityLifecycleCallbacks;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.Movie;
|
||||||
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.MediaMetadataRetriever;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.media.MediaPlayer.OnInfoListener;
|
||||||
|
import android.media.MediaPlayer.OnPreparedListener;
|
||||||
|
import android.media.MediaPlayer.OnVideoSizeChangedListener;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.TextureView;
|
||||||
|
import android.view.TextureView.SurfaceTextureListener;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.FrameLayout.LayoutParams;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.ImageView.ScaleType;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mobile.auth.gatewayauth.LoginAuthActivity;
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import com.mobile.auth.gatewayauth.model.TokenRet;
|
||||||
|
import com.sean.rao.ali_auth.common.CacheManage;
|
||||||
|
import com.sean.rao.ali_auth.common.GifAnimationDrawable;
|
||||||
|
import com.sean.rao.ali_auth.utils.AppUtils;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
|
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Package: com.aliqin.mytel
|
||||||
|
* @ClassName: NativeBackgroundAdapter
|
||||||
|
* @Description: 类作用描述
|
||||||
|
* @Author: liuqi
|
||||||
|
* @CreateDate: 2021/4/29 4:53 PM
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class NativeBackgroundAdapter extends LoginParams{
|
||||||
|
private volatile OnGifListener onGifListener;
|
||||||
|
private volatile GifAnimationDrawable gifAnimationDrawable;
|
||||||
|
private CacheManage mCacheManage;
|
||||||
|
private ExecutorService mExecutorService;
|
||||||
|
private String key, path;
|
||||||
|
|
||||||
|
public NativeBackgroundAdapter(CacheManage cacheManage, ExecutorService executorService, String key) {
|
||||||
|
this.key = key;
|
||||||
|
this.path = jsonObject.getString("pageBackgroundPath");
|
||||||
|
mCacheManage = cacheManage;
|
||||||
|
mExecutorService = executorService;
|
||||||
|
mCacheManage.checkAndCreateBitmapCache();
|
||||||
|
|
||||||
|
if ("gifPath".equals(key)) {
|
||||||
|
if (null == mCacheManage.getBitmap(path)) {
|
||||||
|
getAssetGifFirstFrame(mContext, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("videoPath".equals(key)) {
|
||||||
|
if (null == mCacheManage.getBitmap(path)) {
|
||||||
|
mExecutorService.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Bitmap bitmap = getAssetVideoCoverBitmap(mContext.getAssets(), path);
|
||||||
|
if(null!=bitmap) {
|
||||||
|
mCacheManage.cacheBitmap(path, bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载布局
|
||||||
|
*
|
||||||
|
* @param frameLayout 容器
|
||||||
|
* @param backgroundColor 背景颜色
|
||||||
|
*/
|
||||||
|
public void solveView(final FrameLayout frameLayout, String backgroundColor) {
|
||||||
|
if ("imagePath".equals(key)) {
|
||||||
|
ImageView imageView = new ImageView(frameLayout.getContext());
|
||||||
|
LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
|
||||||
|
imageView.setScaleType(ScaleType.CENTER_CROP);
|
||||||
|
imageView.setImageDrawable(toDrawable(path, frameLayout.getContext()));
|
||||||
|
frameLayout.addView(imageView, params);
|
||||||
|
if (!TextUtils.isEmpty(backgroundColor)) {
|
||||||
|
imageView.setBackgroundColor(Color.parseColor(backgroundColor));
|
||||||
|
}
|
||||||
|
} else if ("gifPath".equals(key)) {
|
||||||
|
final ImageView imageView = new ImageView(frameLayout.getContext());
|
||||||
|
LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
|
||||||
|
imageView.setScaleType(ScaleType.CENTER_CROP);
|
||||||
|
if (!TextUtils.isEmpty(backgroundColor)) {
|
||||||
|
imageView.setBackgroundColor(Color.parseColor(backgroundColor));
|
||||||
|
}
|
||||||
|
frameLayout.addView(imageView, params);
|
||||||
|
if (gifAnimationDrawable != null) {
|
||||||
|
playGif(imageView, gifAnimationDrawable);
|
||||||
|
} else {
|
||||||
|
if (!TextUtils.isEmpty(backgroundColor)) {
|
||||||
|
imageView.setBackgroundColor(Color.parseColor(backgroundColor));
|
||||||
|
}
|
||||||
|
onGifListener = new OnGifListener() {
|
||||||
|
@Override
|
||||||
|
public void onGifDownloaded(final GifAnimationDrawable drawable) {
|
||||||
|
if (drawable != null && null != imageView) {
|
||||||
|
imageView.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
gifAnimationDrawable = drawable;
|
||||||
|
playGif(imageView, drawable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFirstFrame(final Bitmap bitmap) {
|
||||||
|
imageView.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (null == gifAnimationDrawable) {
|
||||||
|
imageView.setImageBitmap(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (null != mCacheManage.getBitmap(path)) {
|
||||||
|
imageView.setImageBitmap(mCacheManage.getBitmap(path));
|
||||||
|
}
|
||||||
|
readGifAsset(frameLayout.getContext(), path);
|
||||||
|
}
|
||||||
|
} else if ("videoPath".equals(key)) {
|
||||||
|
playVideo(frameLayout, path, backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建关闭按钮
|
||||||
|
createImageButton(frameLayout, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取asset文件夹视频封面
|
||||||
|
*
|
||||||
|
* @param assetManager
|
||||||
|
* @param videoPath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap getAssetVideoCoverBitmap(AssetManager assetManager, String videoPath) {
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||||
|
try {
|
||||||
|
AssetFileDescriptor afd = assetManager.openFd(videoPath);
|
||||||
|
retriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
|
||||||
|
//获得第一帧图片
|
||||||
|
bitmap = retriever.getFrameAtTime();
|
||||||
|
try {
|
||||||
|
retriever.release();
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException | IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
Log.e("NativeBackgroundAdapter", "getAssetVideoBitmap:" + ex.getMessage());
|
||||||
|
}
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本地gif第一帧
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
public void getAssetGifFirstFrame(final Context context, final String path) {
|
||||||
|
mExecutorService.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
InputStream inputStream = context.getAssets().open(path);
|
||||||
|
// InputStream inputStream = DownloadFile.getImageToInputStream(path);
|
||||||
|
Movie gif = Movie.decodeStream(inputStream);
|
||||||
|
final Bitmap firstFrame = Bitmap.createBitmap(gif.width(), gif.height(), Bitmap.Config.ARGB_8888);
|
||||||
|
Canvas canvas = new Canvas(firstFrame);
|
||||||
|
gif.draw(canvas, 0, 0);
|
||||||
|
canvas.save();
|
||||||
|
mCacheManage.cacheBitmap(path, firstFrame);
|
||||||
|
OnGifListener gifListener = onGifListener;
|
||||||
|
if (gifListener != null) {
|
||||||
|
gifListener.onFirstFrame(firstFrame);
|
||||||
|
}
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("NativeBackgroundAdapter", "getGifFirstFrame:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放视频
|
||||||
|
*
|
||||||
|
* @param frameLayout
|
||||||
|
* @param path url或者路径
|
||||||
|
* @param backgroundColor
|
||||||
|
*/
|
||||||
|
@TargetApi(VERSION_CODES.JELLY_BEAN)
|
||||||
|
private void playVideo(final FrameLayout frameLayout, final String path, String backgroundColor) {
|
||||||
|
final MediaPlayer[] mediaPlayer = {new MediaPlayer()};
|
||||||
|
final TextureView textureView = new TextureView(frameLayout.getContext());
|
||||||
|
LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
|
||||||
|
frameLayout.addView(textureView, params);
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
||||||
|
textureView.setBackground(null);
|
||||||
|
}
|
||||||
|
final ImageView ivCover = new ImageView(frameLayout.getContext());
|
||||||
|
LayoutParams paramsIv = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
|
||||||
|
ivCover.setScaleType(ScaleType.CENTER_CROP);
|
||||||
|
if (null != mCacheManage.getBitmap(path)) {
|
||||||
|
ivCover.setImageBitmap(mCacheManage.getBitmap(path));
|
||||||
|
} else {
|
||||||
|
if (!TextUtils.isEmpty(backgroundColor)) {
|
||||||
|
frameLayout.setBackgroundColor(Color.parseColor(backgroundColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frameLayout.addView(ivCover, paramsIv);
|
||||||
|
final ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivityResumed(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
if (mediaPlayer[0] != null && !mediaPlayer[0].isPlaying()) {
|
||||||
|
mediaPlayer[0].start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
if (mediaPlayer[0] != null && mediaPlayer[0].isPlaying()) {
|
||||||
|
mediaPlayer[0].pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
if (mediaPlayer[0] != null && mediaPlayer[0].isPlaying()) {
|
||||||
|
mediaPlayer[0].stop();
|
||||||
|
mediaPlayer[0].release();
|
||||||
|
mediaPlayer[0] = null;
|
||||||
|
}
|
||||||
|
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
((Application)frameLayout.getContext()).registerActivityLifecycleCallbacks(
|
||||||
|
activityLifecycleCallbacks);
|
||||||
|
mediaPlayer[0].setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
|
mediaPlayer[0].setLooping(true);
|
||||||
|
mediaPlayer[0].setVolume(0, 0);
|
||||||
|
AssetFileDescriptor afd;
|
||||||
|
try {
|
||||||
|
afd = frameLayout.getContext().getAssets().openFd(path);
|
||||||
|
mediaPlayer[0].setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
|
||||||
|
afd.getLength());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("NativeBackgroundAdapter", "playVideo===readAssets:" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
||||||
|
mediaPlayer[0].setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mediaPlayer[0].setOnPreparedListener(new OnPreparedListener() {
|
||||||
|
@Override
|
||||||
|
public void onPrepared(MediaPlayer mp) {
|
||||||
|
mediaPlayer[0].setOnInfoListener(new OnInfoListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onInfo(MediaPlayer mp, int what, int extra) {
|
||||||
|
if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
|
||||||
|
ivCover.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mediaPlayer[0].start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mediaPlayer[0].setOnVideoSizeChangedListener(new OnVideoSizeChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
|
||||||
|
int mVideoHeight = mediaPlayer[0].getVideoHeight();
|
||||||
|
int mVideoWidth = mediaPlayer[0].getVideoWidth();
|
||||||
|
updateTextureViewSizeCenter(textureView, mVideoWidth, mVideoHeight);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mediaPlayer[0].prepareAsync();
|
||||||
|
textureView.setSurfaceTextureListener(new SurfaceTextureListener() {
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width,
|
||||||
|
int height) {
|
||||||
|
Surface mSurface = new Surface(surface);
|
||||||
|
mediaPlayer[0].setSurface(mSurface);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width,
|
||||||
|
int height) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
|
||||||
|
if (mediaPlayer[0] != null && mediaPlayer[0].isPlaying()) {
|
||||||
|
mediaPlayer[0].pause();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置视频适应模式为center_crop
|
||||||
|
*
|
||||||
|
* @param textureView
|
||||||
|
* @param mVideoWidth
|
||||||
|
* @param mVideoHeight
|
||||||
|
*/
|
||||||
|
private void updateTextureViewSizeCenter(TextureView textureView, int mVideoWidth, int mVideoHeight) {
|
||||||
|
|
||||||
|
float sx = (float)textureView.getWidth() / (float)mVideoWidth;
|
||||||
|
float sy = (float)textureView.getHeight() / (float)mVideoHeight;
|
||||||
|
|
||||||
|
Matrix matrix = new Matrix();
|
||||||
|
float maxScale = Math.max(sx, sy);
|
||||||
|
|
||||||
|
//第1步:把视频区移动到View区,使两者中心点重合.
|
||||||
|
matrix.preTranslate((textureView.getWidth() - mVideoWidth) / 2, (textureView.getHeight() - mVideoHeight) / 2);
|
||||||
|
|
||||||
|
//第2步:因为默认视频是fitXY的形式显示的,所以首先要缩放还原回来.
|
||||||
|
matrix.preScale(mVideoWidth / (float)textureView.getWidth(), mVideoHeight / (float)textureView.getHeight());
|
||||||
|
|
||||||
|
//第3步,等比例放大或缩小,直到视频区的一边超过View一边, 另一边与View的另一边相等. 因为超过的部分超出了View的范围,所以是不会显示的,相当于裁剪了.
|
||||||
|
matrix.postScale(maxScale, maxScale, textureView.getWidth() / 2,
|
||||||
|
textureView.getHeight() / 2);//后两个参数坐标是以整个View的坐标系以参考的
|
||||||
|
textureView.setTransform(matrix);
|
||||||
|
textureView.postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从本地读取gif
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
private void readGifAsset(final Context context, final String path) {
|
||||||
|
mExecutorService.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
AssetManager assetManager = context.getAssets();
|
||||||
|
try {
|
||||||
|
InputStream inputStream = assetManager.open(
|
||||||
|
path);
|
||||||
|
final GifAnimationDrawable gifAnimationDrawable = new GifAnimationDrawable(inputStream);
|
||||||
|
if (onGifListener != null) {
|
||||||
|
onGifListener.onGifDownloaded(gifAnimationDrawable);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("NativeBackgroundAdapter", "read gif asset:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放gif动画
|
||||||
|
*
|
||||||
|
* @param imageView
|
||||||
|
* @param gifAnimationDrawable
|
||||||
|
*/
|
||||||
|
private void playGif(final ImageView imageView, final GifAnimationDrawable gifAnimationDrawable) {
|
||||||
|
Log.e("NativeBackgroundAdapter", "playGif asset");
|
||||||
|
final ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStarted(Activity activity) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResumed(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
if (gifAnimationDrawable != null && !gifAnimationDrawable.isRunning()) {
|
||||||
|
imageView.postDelayed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
gifAnimationDrawable.start();
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityPaused(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
if (gifAnimationDrawable != null && gifAnimationDrawable.isRunning()) {
|
||||||
|
gifAnimationDrawable.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityStopped(Activity activity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityDestroyed(Activity activity) {
|
||||||
|
if (activity instanceof LoginAuthActivity) {
|
||||||
|
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
((Application)imageView.getContext()).registerActivityLifecycleCallbacks(
|
||||||
|
activityLifecycleCallbacks);
|
||||||
|
imageView.setImageDrawable(gifAnimationDrawable);
|
||||||
|
gifAnimationDrawable.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnGifListener {
|
||||||
|
/**
|
||||||
|
* gif下载完成监听
|
||||||
|
*
|
||||||
|
* @param drawable
|
||||||
|
*/
|
||||||
|
void onGifDownloaded(GifAnimationDrawable drawable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取第一帧完成监听
|
||||||
|
*
|
||||||
|
* @param bitmap
|
||||||
|
*/
|
||||||
|
void onFirstFrame(Bitmap bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建图片按钮
|
||||||
|
* @param frameLayout
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected void createImageButton(final FrameLayout frameLayout, final String path){
|
||||||
|
JSONObject customRetureBtn = jsonObject.getJSONObject("customReturnBtn");
|
||||||
|
if (customRetureBtn != null) {
|
||||||
|
try{
|
||||||
|
LinearLayout linearLayout = new LinearLayout(frameLayout.getContext());
|
||||||
|
/// 是否留出状态栏的高度
|
||||||
|
// linearLayout.setFitsSystemWindows(false);
|
||||||
|
LayoutParams linearLayoutParams = new LayoutParams(MATCH_PARENT, WRAP_CONTENT);
|
||||||
|
ImageButton imageButton = new ImageButton(frameLayout.getContext());
|
||||||
|
imageButton.setPadding(0, 0, 0, 0);
|
||||||
|
imageButton.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
imageButton.setScaleType(ScaleType.values()[customRetureBtn.getIntValue("imgScaleType")]);
|
||||||
|
imageButton.setImageDrawable(UtilTool.getBitmapToBitmapDrawable(frameLayout.getContext(), UtilTool.flutterToPath(customRetureBtn.getString("imgPath"))));
|
||||||
|
LayoutParams buttonParams = new LayoutParams(
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("width")),
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("height"))
|
||||||
|
);
|
||||||
|
buttonParams.setMargins(
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("left")),
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("top")),
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("right")),
|
||||||
|
AppUtils.dp2px(frameLayout.getContext(), customRetureBtn.getIntValue("bottom"))
|
||||||
|
);
|
||||||
|
imageButton.setOnClickListener(v -> {
|
||||||
|
eventSink.success(UtilTool.resultFormatData("700000", null, null));
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
});
|
||||||
|
|
||||||
|
linearLayout.addView(imageButton, buttonParams);
|
||||||
|
frameLayout.addView(linearLayout, linearLayoutParams);
|
||||||
|
} catch (IOException e) {
|
||||||
|
eventSink.success(UtilTool.resultFormatData("500000", null, e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Drawable toDrawable(String imgUrl, Context context) {
|
||||||
|
Drawable drawable = null;
|
||||||
|
Bitmap bitmap = null;
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
AssetManager assetManager = context.getAssets();
|
||||||
|
inputStream = assetManager.open(imgUrl);
|
||||||
|
bitmap = BitmapFactory.decodeStream(inputStream);
|
||||||
|
drawable = new BitmapDrawable(context.getResources(), bitmap);
|
||||||
|
} catch (Exception var6) {
|
||||||
|
var6.printStackTrace();
|
||||||
|
if (bitmap != null) {
|
||||||
|
bitmap.recycle();
|
||||||
|
}
|
||||||
|
Log.e("AuthSDK", "e=" + var6.toString());
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.sean.rao.ali_auth.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: android
|
||||||
|
* @Package: com.sean.rao.ali_auth.common
|
||||||
|
* @ClassName: OnListener
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 6/13/22 4:21 PM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 6/13/22 4:21 PM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public interface OnListener {
|
||||||
|
void CallBack(boolean status);
|
||||||
|
}
|
||||||
@ -0,0 +1,223 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Space;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.sean.rao.ali_auth.common.Constant;
|
||||||
|
|
||||||
|
import com.sean.rao.ali_auth.common.LoginParams;
|
||||||
|
import com.sean.rao.ali_auth.utils.AppUtils;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
public abstract class BaseUIConfig extends LoginParams {
|
||||||
|
public int mScreenWidthDp;
|
||||||
|
public int mScreenHeightDp;
|
||||||
|
|
||||||
|
public static BaseUIConfig init(int type) {
|
||||||
|
isChecked = false;
|
||||||
|
switch (type) {
|
||||||
|
case Constant.FULL_PORT:
|
||||||
|
return new FullPortConfig();
|
||||||
|
case Constant.FULL_LAND:
|
||||||
|
return new FullLandConfig();
|
||||||
|
case Constant.DIALOG_PORT:
|
||||||
|
return new DialogPortConfig();
|
||||||
|
case Constant.DIALOG_LAND:
|
||||||
|
return new DialogLandConfig();
|
||||||
|
case Constant.DIALOG_BOTTOM:
|
||||||
|
return new DialogBottomConfig();
|
||||||
|
case Constant.CUSTOM_XML:
|
||||||
|
return new CustomXmlConfig();
|
||||||
|
default:
|
||||||
|
if (jsonObject.getString("pageBackgroundPath") != null && !jsonObject.getString("pageBackgroundPath").isEmpty()) {
|
||||||
|
if (jsonObject.getString("pageBackgroundPath").equals("xml")) {
|
||||||
|
return new CustomXmlConfig();
|
||||||
|
} else if (jsonObject.getString("pageBackgroundPath").equals("view")) {
|
||||||
|
return new CustomViewConfig();
|
||||||
|
} else {
|
||||||
|
return new CustomAssetsConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除自定义布局参数,防止内存溢出
|
||||||
|
*/
|
||||||
|
public BaseUIConfig() {
|
||||||
|
// 防止内存泄漏
|
||||||
|
mAuthHelper.removeAuthRegisterXmlConfig();
|
||||||
|
mAuthHelper.removeAuthRegisterViewConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方布局设置
|
||||||
|
* @param marginTop
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected View initSwitchView(int marginTop) {
|
||||||
|
JSONObject customThirdView = jsonObject.getJSONObject("customThirdView");
|
||||||
|
/// 名称列表
|
||||||
|
JSONArray customThirdViewName = customThirdView.getJSONArray("viewItemName");
|
||||||
|
/// 图片路径列表
|
||||||
|
JSONArray customThirdViewItem = customThirdView.getJSONArray("viewItemPath");
|
||||||
|
if (customThirdViewName != null && customThirdViewItem != null) {
|
||||||
|
LinearLayout linearLayout = new LinearLayout(mContext);
|
||||||
|
// 创建一个最大宽度和适量高度的布局
|
||||||
|
LinearLayout.LayoutParams LayoutParams = new LinearLayout.LayoutParams(
|
||||||
|
customThirdView.getFloatValue("width") > 0 ? AppUtils.dp2px(mContext, customThirdView.getFloatValue("width")) : LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
customThirdView.getFloatValue("height") > 0 ? AppUtils.dp2px(mContext, customThirdView.getFloatValue("height")) : LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
);
|
||||||
|
|
||||||
|
// 居中边距
|
||||||
|
LayoutParams.setMargins(
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("left") > 0 ? customThirdView.getFloatValue("left") : 10),
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("top") > 0 ? customThirdView.getFloatValue("top") : marginTop),
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("right") > 0 ? customThirdView.getFloatValue("right") : 10),
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("bottom") > 0 ? customThirdView.getFloatValue("bottom") : 10)
|
||||||
|
);
|
||||||
|
linearLayout.setLayoutParams(LayoutParams);
|
||||||
|
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
linearLayout.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
|
|
||||||
|
for (int i = 0; i < customThirdViewItem.size(); i++) {
|
||||||
|
if (customThirdViewItem.get(i) != null && !String.valueOf(customThirdViewItem.get(i)).isEmpty()) {
|
||||||
|
int finalI = i;
|
||||||
|
/// 每个item布局
|
||||||
|
LinearLayout itemLinearLayout = new LinearLayout(mContext);
|
||||||
|
/// 按钮和文字布局
|
||||||
|
itemLinearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
/// 按钮控件
|
||||||
|
ImageButton itemButton = new ImageButton(mActivity);
|
||||||
|
/// 需要转化路径
|
||||||
|
try {
|
||||||
|
itemButton.setBackground(
|
||||||
|
UtilTool.getBitmapToBitmapDrawable(
|
||||||
|
mContext,
|
||||||
|
UtilTool.flutterToPath(String.valueOf(customThirdViewItem.get(i)))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// eventSink.success(UtilTool.resultFormatData("500000", null, e.getMessage()));
|
||||||
|
showResult("500000", "出现错误", e.getMessage());
|
||||||
|
}
|
||||||
|
ViewGroup.LayoutParams buttonLayoutParams = new ViewGroup.LayoutParams(
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("itemWidth") > 0 ? customThirdView.getFloatValue("itemWidth") : 60),
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("itemHeight") > 0 ? customThirdView.getFloatValue("itemHeight") : 60)
|
||||||
|
);
|
||||||
|
itemButton.setLayoutParams(buttonLayoutParams);
|
||||||
|
|
||||||
|
/// 第三方按钮的点击事件
|
||||||
|
itemButton.setOnClickListener(v -> {
|
||||||
|
// 判断是否隐藏toast
|
||||||
|
showResult("700005", "点击第三方登录按钮", finalI);
|
||||||
|
// eventSink.success(UtilTool.resultFormatData("600019", null, finalI));
|
||||||
|
// if (!jsonObject.getBooleanValue("isHideToast") && !isChecked) {
|
||||||
|
// Toaster.show(jsonObject.getString("toastText"));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
if (jsonObject.getBooleanValue("autoQuitPage")) {
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
itemLinearLayout.addView(itemButton);
|
||||||
|
|
||||||
|
Object itemName = customThirdViewName.get(i);
|
||||||
|
if (itemName != null && !String.valueOf(itemName).isEmpty()) {
|
||||||
|
// 按钮下文字控件
|
||||||
|
TextView textView = new TextView(mContext);
|
||||||
|
textView.setText(String.valueOf(itemName));
|
||||||
|
// 文字颜色
|
||||||
|
textView.setTextColor(customThirdView.getString("color") != null && !customThirdView.getString("color").isEmpty() ? Color.parseColor(customThirdView.getString("color")) : Color.BLACK);
|
||||||
|
textView.setTextSize(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
customThirdView.getFloatValue("size") > 0 ? customThirdView.getFloatValue("size") : 14F
|
||||||
|
);
|
||||||
|
textView.setGravity(Gravity.CENTER);
|
||||||
|
itemLinearLayout.addView(textView);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 新增按钮间距控件
|
||||||
|
if (i > 0 && i < customThirdViewItem.size()) {
|
||||||
|
Space space = new Space(mContext);
|
||||||
|
space.setLayoutParams(new ViewGroup.LayoutParams(
|
||||||
|
AppUtils.dp2px(mContext, customThirdView.getFloatValue("space") > 0 ? customThirdView.getFloatValue("space") : 10),
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT)
|
||||||
|
);
|
||||||
|
linearLayout.addView(space);
|
||||||
|
}
|
||||||
|
/// 将item放入布局中
|
||||||
|
linearLayout.addView(itemLinearLayout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return linearLayout;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新屏幕
|
||||||
|
* @param authPageScreenOrientation
|
||||||
|
*/
|
||||||
|
protected void updateScreenSize(int authPageScreenOrientation) {
|
||||||
|
int screenHeightDp = AppUtils.px2dp(mContext, AppUtils.getPhoneHeightPixels(mContext));
|
||||||
|
int screenWidthDp = AppUtils.px2dp(mContext, AppUtils.getPhoneWidthPixels(mContext));
|
||||||
|
int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
|
||||||
|
if (authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
|
||||||
|
authPageScreenOrientation = mActivity.getRequestedOrientation();
|
||||||
|
}
|
||||||
|
if (authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||||
|
|| authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
||||||
|
|| authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE) {
|
||||||
|
rotation = Surface.ROTATION_90;
|
||||||
|
} else if (authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||||
|
|| authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
|
||||||
|
|| authPageScreenOrientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT) {
|
||||||
|
rotation = Surface.ROTATION_180;
|
||||||
|
}
|
||||||
|
switch (rotation) {
|
||||||
|
case Surface.ROTATION_0:
|
||||||
|
case Surface.ROTATION_180:
|
||||||
|
mScreenWidthDp = screenWidthDp;
|
||||||
|
mScreenHeightDp = screenHeightDp;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_90:
|
||||||
|
case Surface.ROTATION_270:
|
||||||
|
mScreenWidthDp = screenHeightDp;
|
||||||
|
mScreenHeightDp = screenWidthDp;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void configAuthPage();
|
||||||
|
|
||||||
|
private void configBuild(){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在横屏APP弹竖屏一键登录页面或者竖屏APP弹横屏授权页时处理特殊逻辑
|
||||||
|
* Android8.0只能启动SCREEN_ORIENTATION_BEHIND模式的Activity
|
||||||
|
*/
|
||||||
|
public void onResume() {}
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterXmlConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.ui.AbstractPnsViewDelegate;
|
||||||
|
import com.sean.rao.ali_auth.R;
|
||||||
|
import com.sean.rao.ali_auth.common.CacheManage;
|
||||||
|
import com.sean.rao.ali_auth.common.MediaFileUtil;
|
||||||
|
import com.sean.rao.ali_auth.common.NativeBackgroundAdapter;
|
||||||
|
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xml文件方便预览
|
||||||
|
* 可以通过addAuthRegisterXmlConfig一次性统一添加授权页的所有自定义view
|
||||||
|
*/
|
||||||
|
public class CustomAssetsConfig extends BaseUIConfig {
|
||||||
|
private CacheManage mCacheManage;
|
||||||
|
private ExecutorService mThreadExecutor;
|
||||||
|
private NativeBackgroundAdapter nativeBackgroundAdapter;
|
||||||
|
public CustomAssetsConfig() {
|
||||||
|
super();
|
||||||
|
String fileType = "imagePath";
|
||||||
|
if (jsonObject.getString("pageBackgroundPath") != null && !jsonObject.getString("pageBackgroundPath").isEmpty()) {
|
||||||
|
if (MediaFileUtil.isImageGifFileType(jsonObject.getString("pageBackgroundPath"))) {
|
||||||
|
fileType = "gifPath";
|
||||||
|
} else if (MediaFileUtil.isVideoFileType(jsonObject.getString("pageBackgroundPath"))) {
|
||||||
|
fileType = "videoPath";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCacheManage=new CacheManage(mActivity.getApplication());
|
||||||
|
mThreadExecutor=new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
|
||||||
|
Runtime.getRuntime().availableProcessors(),
|
||||||
|
0,
|
||||||
|
TimeUnit.SECONDS,
|
||||||
|
new ArrayBlockingQueue<Runnable>(10),
|
||||||
|
new ThreadPoolExecutor.CallerRunsPolicy()
|
||||||
|
);
|
||||||
|
nativeBackgroundAdapter = new NativeBackgroundAdapter(mCacheManage, mThreadExecutor, fileType);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
updateScreenSize(authPageOrientation);
|
||||||
|
//sdk默认控件的区域是marginTop50dp
|
||||||
|
int designHeight = mScreenHeightDp - 50;
|
||||||
|
int unit = designHeight / 10;
|
||||||
|
mAuthHelper.addAuthRegisterXmlConfig(new AuthRegisterXmlConfig.Builder()
|
||||||
|
.setLayout(R.layout.authsdk_widget_custom_layout, new AbstractPnsViewDelegate() {
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view) {
|
||||||
|
final FrameLayout fly_container = view.findViewById(R.id.fly_container);
|
||||||
|
// final Button close = view.findViewById(R.id.close);
|
||||||
|
// fly_container.setOnApplyWindowInsetsListener();
|
||||||
|
nativeBackgroundAdapter.solveView(fly_container, "#3F51B5");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build());
|
||||||
|
|
||||||
|
//添加自定义切换其他登录方式
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initSwitchView(420))
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.CustomInterface;
|
||||||
|
|
||||||
|
import static com.nirvana.tools.core.AppUtils.dp2px;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 号码栏水平位置的自定义view 推荐使用addAuthRegistViewConfig 可以添加到相对精准的位置
|
||||||
|
*/
|
||||||
|
public class CustomViewConfig extends BaseUIConfig {
|
||||||
|
|
||||||
|
public CustomViewConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initSwitchView(350))
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY)
|
||||||
|
.setCustomInterface(new CustomInterface() {
|
||||||
|
@Override
|
||||||
|
public void onClick(Context context) {
|
||||||
|
// Toast.makeText(mContext, "切换到短信登录方式", Toast.LENGTH_SHORT).show();
|
||||||
|
// Intent pIntent = new Intent(mActivity, MessageActivity.class);
|
||||||
|
// mActivity.startActivityForResult(pIntent, 1002);
|
||||||
|
// mAuthHelper.quitLoginPage();
|
||||||
|
}
|
||||||
|
}).build());
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("number_logo", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initNumberLogoView())
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_NUMBER)
|
||||||
|
.setCustomInterface(new CustomInterface() {
|
||||||
|
@Override
|
||||||
|
public void onClick(Context context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}).build());
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("back_btn", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initBackBtn())
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_TITLE_BAR)
|
||||||
|
.setCustomInterface(new CustomInterface() {
|
||||||
|
@Override
|
||||||
|
public void onClick(Context context) {
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
mActivity.finish();
|
||||||
|
}
|
||||||
|
}).build());
|
||||||
|
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageView initNumberLogoView() {
|
||||||
|
ImageView pImageView = new ImageView(mContext);
|
||||||
|
// pImageView.setImageResource(R.drawable.phone);
|
||||||
|
pImageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||||
|
RelativeLayout.LayoutParams pParams = new RelativeLayout.LayoutParams(dp2px(mContext, 30), dp2px(mContext, 30));
|
||||||
|
pParams.setMargins(dp2px(mContext, 100), 0, 0, 0);
|
||||||
|
pImageView.setLayoutParams(pParams);
|
||||||
|
return pImageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageView initBackBtn() {
|
||||||
|
ImageView pImageView = new ImageView(mContext);
|
||||||
|
// pImageView.setImageResource(R.drawable.icon_close);
|
||||||
|
pImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||||
|
RelativeLayout.LayoutParams pParams = new RelativeLayout.LayoutParams(dp2px(mContext, 20), dp2px(mContext, 20));
|
||||||
|
pParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE);
|
||||||
|
pParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
|
||||||
|
pParams.setMargins(dp2px(mContext, 12.0F), 0, 0, 0);
|
||||||
|
pImageView.setLayoutParams(pParams);
|
||||||
|
return pImageView;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterXmlConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.ui.AbstractPnsViewDelegate;
|
||||||
|
import com.sean.rao.ali_auth.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xml文件方便预览
|
||||||
|
* 可以通过addAuthRegisterXmlConfig一次性统一添加授权页的所有自定义view
|
||||||
|
*/
|
||||||
|
public class CustomXmlConfig extends BaseUIConfig {
|
||||||
|
|
||||||
|
public CustomXmlConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getCustomXml = mContext.getResources().getIdentifier("custom_full_port", "layout", mContext.getPackageName());
|
||||||
|
// 判断是否有自定义布局文件,没有则加载默认布局文件
|
||||||
|
if(getCustomXml == 0){
|
||||||
|
getCustomXml = mContext.getResources().getIdentifier("custom_full_port", "layout", mContext.getPackageName());
|
||||||
|
}
|
||||||
|
View customXmlLayout = LayoutInflater.from(mContext).inflate(getCustomXml, new RelativeLayout(mContext), false);
|
||||||
|
mAuthHelper.addAuthRegisterXmlConfig(new AuthRegisterXmlConfig.Builder()
|
||||||
|
.setLayout(getCustomXml, new AbstractPnsViewDelegate() {
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view) {
|
||||||
|
findViewById(R.id.btn_back).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
/// 点击关闭按钮
|
||||||
|
// eventSink.success(UtilTool.resultFormatData("700000", null, null));
|
||||||
|
showResult("700000", "点击返回按钮", "");
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
findViewById(R.id.tv_switch).setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
/// 点击切换其他按钮
|
||||||
|
showResult("700001", "切换到其他方式", "");
|
||||||
|
// eventSink.success(UtilTool.resultFormatData("700001", null, null));
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build());
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.sean.rao.ali_auth.utils.AppUtils;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DialogBottomConfig extends BaseUIConfig {
|
||||||
|
|
||||||
|
public DialogBottomConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
updateScreenSize(authPageOrientation);
|
||||||
|
|
||||||
|
int dialogHeight = (int) (mScreenHeightDp * 0.5f);
|
||||||
|
//sdk默认控件的区域是marginTop50dp
|
||||||
|
int designHeight = dialogHeight - 50;
|
||||||
|
int unit = designHeight / 10;
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initSwitchView(unit * 6))
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
if (jsonObject.containsKey("pageBackgroundPath") && !jsonObject.getString("pageBackgroundPath").isEmpty()) {
|
||||||
|
try {
|
||||||
|
RoundedBitmapDrawable pageBackgroundDrawable = RoundedBitmapDrawableFactory.create(mContext.getResources(), UtilTool.getPathToBitmap(mContext, jsonObject.getString("pageBackgroundPath")));
|
||||||
|
pageBackgroundDrawable.setCornerRadius(AppUtils.dp2px(mContext, jsonObject.getIntValue("pageBackgroundRadius")));
|
||||||
|
config.setPageBackgroundDrawable(pageBackgroundDrawable);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// eventSink.success(UtilTool.resultFormatData("500000", null, e.getMessage()));
|
||||||
|
showResult("500000", "背景处理时出现错误", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.CustomInterface;
|
||||||
|
import com.sean.rao.ali_auth.utils.AppUtils;
|
||||||
|
|
||||||
|
public class DialogLandConfig extends BaseUIConfig{
|
||||||
|
private int mOldScreenOrientation;
|
||||||
|
|
||||||
|
|
||||||
|
public DialogLandConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
mOldScreenOrientation = mActivity.getRequestedOrientation();
|
||||||
|
mActivity.setRequestedOrientation(authPageOrientation);
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
updateScreenSize(authPageOrientation);
|
||||||
|
final int dialogWidth = (int) (mScreenWidthDp * 0.63);
|
||||||
|
final int dialogHeight = (int) (mScreenHeightDp * 0.6);
|
||||||
|
|
||||||
|
//sdk默认控件的区域是marginTop50dp
|
||||||
|
int designHeight = dialogHeight - 50;
|
||||||
|
int unit = designHeight / 10;
|
||||||
|
int logBtnHeight = (int) (unit * 1.2);
|
||||||
|
final int logBtnOffsetY = unit * 3;
|
||||||
|
|
||||||
|
final View switchContainer = createLandDialogCustomSwitchView();
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("number_logo", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initNumberView())
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_NUMBER)
|
||||||
|
.setCustomInterface(new CustomInterface() {
|
||||||
|
@Override
|
||||||
|
public void onClick(Context context) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}).build());
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_other", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_NUMBER)
|
||||||
|
.setView(switchContainer).build());
|
||||||
|
// mAuthHelper.addAuthRegisterXmlConfig(new AuthRegisterXmlConfig.Builder()
|
||||||
|
// .setLayout(R.layout.custom_land_dialog, new AbstractPnsViewDelegate() {
|
||||||
|
// @Override
|
||||||
|
// public void onViewCreated(View view) {
|
||||||
|
// findViewById(R.id.tv_title).setVisibility(View.GONE);
|
||||||
|
// findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(View v) {
|
||||||
|
// mAuthHelper.quitLoginPage();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// int iconTopMargin = AppUtils.dp2px(getContext(), logBtnOffsetY + 50);
|
||||||
|
// View iconContainer = findViewById(R.id.container_icon);
|
||||||
|
// RelativeLayout.LayoutParams iconLayout = (RelativeLayout.LayoutParams) iconContainer.getLayoutParams();
|
||||||
|
// iconLayout.topMargin = iconTopMargin;
|
||||||
|
// iconLayout.width = AppUtils.dp2px(getContext(), dialogWidth / 2 - 60);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .build());
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageView createLandDialogPhoneNumberIcon(int leftMargin) {
|
||||||
|
ImageView imageView = new ImageView(mContext);
|
||||||
|
int size = AppUtils.dp2px(mContext, 23);
|
||||||
|
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(size, size);
|
||||||
|
layoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
|
||||||
|
layoutParams.leftMargin = leftMargin;
|
||||||
|
imageView.setLayoutParams(layoutParams);
|
||||||
|
// imageView.setBackgroundResource(R.drawable.phone);
|
||||||
|
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||||
|
return imageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
private View createLandDialogCustomSwitchView() {
|
||||||
|
// View v = LayoutInflater.from(mContext).inflate(R.layout.custom_switch_other, new RelativeLayout(mContext), false);
|
||||||
|
// RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
// RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||||
|
// layoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
|
||||||
|
// v.setLayoutParams(layoutParams);
|
||||||
|
// return v;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (mOldScreenOrientation != mActivity.getRequestedOrientation()) {
|
||||||
|
mActivity.setRequestedOrientation(mOldScreenOrientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageView initNumberView() {
|
||||||
|
ImageView pImageView = new ImageView(mContext);
|
||||||
|
// pImageView.setImageResource(R.drawable.phone);
|
||||||
|
pImageView.setScaleType(ImageView.ScaleType.FIT_XY);
|
||||||
|
RelativeLayout.LayoutParams pParams = new RelativeLayout.LayoutParams(AppUtils.dp2px(mContext, 30), AppUtils.dp2px(mContext, 30));
|
||||||
|
pParams.setMargins(AppUtils.dp2px(mContext, 30), 0, 0, 0);
|
||||||
|
pImageView.setLayoutParams(pParams);
|
||||||
|
return pImageView;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.graphics.drawable.StateListDrawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
|
||||||
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.sean.rao.ali_auth.common.CustomAuthUIControlClickListener;
|
||||||
|
import com.sean.rao.ali_auth.utils.AppUtils;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DialogPortConfig extends BaseUIConfig {
|
||||||
|
/**
|
||||||
|
* 应用包名
|
||||||
|
*/
|
||||||
|
private String mPackageName;
|
||||||
|
|
||||||
|
public DialogPortConfig() {
|
||||||
|
super();
|
||||||
|
mPackageName = AppUtils.getPackageName(mActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
// 注册 UI 点击事件监听(用户取消、勾选协议等事件)
|
||||||
|
mAuthHelper.setUIClickListener(new CustomAuthUIControlClickListener());
|
||||||
|
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
updateScreenSize(authPageOrientation);
|
||||||
|
|
||||||
|
// 添加第三方登录按钮(如果配置了的话)
|
||||||
|
View switchView = initSwitchView(420);
|
||||||
|
if (switchView != null) {
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(switchView)
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹窗背景
|
||||||
|
String bgPath = jsonObject.getString("pageBackgroundPath");
|
||||||
|
if (bgPath != null && !bgPath.isEmpty()) {
|
||||||
|
// 有背景图片:加载图片并设置圆角
|
||||||
|
try {
|
||||||
|
RoundedBitmapDrawable pageBackgroundDrawable = RoundedBitmapDrawableFactory.create(
|
||||||
|
mContext.getResources(),
|
||||||
|
UtilTool.getPathToBitmap(mContext, bgPath));
|
||||||
|
pageBackgroundDrawable.setCornerRadius(
|
||||||
|
AppUtils.dp2px(mContext, jsonObject.getIntValue("pageBackgroundRadius")));
|
||||||
|
config.setPageBackgroundDrawable(pageBackgroundDrawable);
|
||||||
|
} catch (IOException e) {
|
||||||
|
showResult("500000", "背景处理时出现错误", e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 无背景图片:使用纯色背景 + 圆角
|
||||||
|
int bgColor = Color.WHITE;
|
||||||
|
if (jsonObject.containsKey("backgroundColor")) {
|
||||||
|
Object bgVal = jsonObject.get("backgroundColor");
|
||||||
|
if (bgVal instanceof Integer) {
|
||||||
|
bgColor = (Integer) bgVal;
|
||||||
|
} else if (bgVal instanceof String) {
|
||||||
|
try { bgColor = Color.parseColor((String) bgVal); } catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int cornerRadius = AppUtils.dp2px(mContext, jsonObject.getIntValue("pageBackgroundRadius", 12));
|
||||||
|
GradientDrawable bgDrawable = new GradientDrawable();
|
||||||
|
bgDrawable.setColor(bgColor);
|
||||||
|
bgDrawable.setCornerRadius(cornerRadius);
|
||||||
|
config.setPageBackgroundDrawable(bgDrawable);
|
||||||
|
Log.i("DialogPortConfig", "使用纯色背景: #" + Integer.toHexString(bgColor) + ", 圆角: " + cornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录按钮背景:如果没有设置 logBtnBackgroundPath,使用蓝色圆角背景
|
||||||
|
String btnPath = jsonObject.getString("logBtnBackgroundPath");
|
||||||
|
if (btnPath == null || btnPath.isEmpty()) {
|
||||||
|
int btnRadius = AppUtils.dp2px(mContext, 22);
|
||||||
|
// 正常状态
|
||||||
|
GradientDrawable normalDrawable = new GradientDrawable();
|
||||||
|
normalDrawable.setColor(Color.parseColor("#4A90D9"));
|
||||||
|
normalDrawable.setCornerRadius(btnRadius);
|
||||||
|
// 按下状态
|
||||||
|
GradientDrawable pressedDrawable = new GradientDrawable();
|
||||||
|
pressedDrawable.setColor(Color.parseColor("#3A7BC8"));
|
||||||
|
pressedDrawable.setCornerRadius(btnRadius);
|
||||||
|
|
||||||
|
StateListDrawable btnStateDrawable = new StateListDrawable();
|
||||||
|
btnStateDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
|
||||||
|
btnStateDrawable.addState(new int[]{}, normalDrawable);
|
||||||
|
config.setLogBtnBackgroundDrawable(btnStateDrawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
public class FullLandConfig extends BaseUIConfig {
|
||||||
|
|
||||||
|
private int mOldScreenOrientation;
|
||||||
|
|
||||||
|
public FullLandConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
// mAuthHelper.addAuthRegisterXmlConfig(new AuthRegisterXmlConfig.Builder()
|
||||||
|
// .setLayout(R.layout.custom_port_dialog_action_bar, new AbstractPnsViewDelegate() {
|
||||||
|
// @Override
|
||||||
|
// public void onViewCreated(View view) {
|
||||||
|
// findViewById(R.id.tv_title).setVisibility(View.GONE);
|
||||||
|
// findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(View v) {
|
||||||
|
// mAuthHelper.quitLoginPage();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .build());
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
mOldScreenOrientation = mActivity.getRequestedOrientation();
|
||||||
|
mActivity.setRequestedOrientation(authPageOrientation);
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
updateScreenSize(authPageOrientation);
|
||||||
|
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (mOldScreenOrientation != mActivity.getRequestedOrientation()) {
|
||||||
|
mActivity.setRequestedOrientation(mOldScreenOrientation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.sean.rao.ali_auth.config;
|
||||||
|
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
|
import com.mobile.auth.gatewayauth.AuthRegisterViewConfig;
|
||||||
|
import com.sean.rao.ali_auth.common.CustomAuthUIControlClickListener;
|
||||||
|
|
||||||
|
public class FullPortConfig extends BaseUIConfig {
|
||||||
|
private final String TAG = "全屏竖屏样式";
|
||||||
|
|
||||||
|
public FullPortConfig() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configAuthPage() {
|
||||||
|
mAuthHelper.setUIClickListener(new CustomAuthUIControlClickListener());
|
||||||
|
//添加自定义切换其他登录方式
|
||||||
|
mAuthHelper.addAuthRegistViewConfig("switch_msg", new AuthRegisterViewConfig.Builder()
|
||||||
|
.setView(initSwitchView(420))
|
||||||
|
.setRootViewId(AuthRegisterViewConfig.RootViewId.ROOT_VIEW_ID_BODY)
|
||||||
|
// .setCustomInterface(new CustomInterface() {
|
||||||
|
// @Override
|
||||||
|
// public void onClick(Context context) {
|
||||||
|
// JSONObject jsonObj = new JSONObject();
|
||||||
|
// jsonObj.put("code", "7000001");
|
||||||
|
// jsonObj.put("data", "");
|
||||||
|
// jsonObj.put("msg", "切换到短信登录方式");
|
||||||
|
// eventSink.success(jsonObj);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
.build());
|
||||||
|
int authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
|
||||||
|
if (Build.VERSION.SDK_INT == 26) {
|
||||||
|
authPageOrientation = ActivityInfo.SCREEN_ORIENTATION_BEHIND;
|
||||||
|
}
|
||||||
|
mAuthHelper.setAuthUIConfig(config.setScreenOrientation(authPageOrientation).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,367 @@
|
|||||||
|
package com.sean.rao.ali_auth.login;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mobile.auth.gatewayauth.AuthUIConfig;
|
||||||
|
import com.mobile.auth.gatewayauth.PhoneNumberAuthHelper;
|
||||||
|
import com.mobile.auth.gatewayauth.PreLoginResultListener;
|
||||||
|
import com.mobile.auth.gatewayauth.ResultCode;
|
||||||
|
import com.mobile.auth.gatewayauth.TokenResultListener;
|
||||||
|
import com.mobile.auth.gatewayauth.model.TokenRet;
|
||||||
|
import com.sean.rao.ali_auth.common.LoginParams;
|
||||||
|
import com.sean.rao.ali_auth.config.BaseUIConfig;
|
||||||
|
import com.sean.rao.ali_auth.utils.UtilTool;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进app直接登录的场景
|
||||||
|
*/
|
||||||
|
public class OneKeyLoginPublic extends LoginParams {
|
||||||
|
private static final String TAG = OneKeyLoginPublic.class.getSimpleName();
|
||||||
|
|
||||||
|
public OneKeyLoginPublic(Activity activity, EventChannel.EventSink _eventSink, Object arguments){
|
||||||
|
mActivity = activity;
|
||||||
|
mContext = activity.getBaseContext();
|
||||||
|
eventSink = _eventSink;
|
||||||
|
jsonObject = formatParmas(arguments);
|
||||||
|
config = getFormatConfig(jsonObject);
|
||||||
|
|
||||||
|
// 初始化SDK
|
||||||
|
sdkInit();
|
||||||
|
mUIConfig = BaseUIConfig.init(jsonObject.getIntValue("pageType"));
|
||||||
|
if (jsonObject.getBooleanValue("isDelay")) {
|
||||||
|
} else {
|
||||||
|
// 非延时的情况下需要判断是否给予登录
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
oneKeyLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化SDK
|
||||||
|
*/
|
||||||
|
private void sdkInit() {
|
||||||
|
mTokenResultListener=new TokenResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onTokenSuccess(String s) {
|
||||||
|
sdkAvailable = true;
|
||||||
|
try {
|
||||||
|
Log.i(TAG, "checkEnvAvailable:" + s);
|
||||||
|
TokenRet tokenRet = TokenRet.fromJson(s);
|
||||||
|
if (ResultCode.CODE_ERROR_ENV_CHECK_SUCCESS.equals(tokenRet.getCode())) {
|
||||||
|
/// 延时登录的情况下加速拉起一键登录页面
|
||||||
|
if (jsonObject.getBooleanValue("isDelay")) {
|
||||||
|
accelerateLoginPage(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ResultCode.CODE_SUCCESS.equals(tokenRet.getCode())) {
|
||||||
|
Log.i("TAG", "获取token成功:" + s);
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
}
|
||||||
|
showResult(tokenRet.getCode(), null, tokenRet.getToken());
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTokenFailed(String s) {
|
||||||
|
sdkAvailable = false;
|
||||||
|
mAuthHelper.hideLoginLoading();
|
||||||
|
Log.e(TAG, "获取token失败:" + s);
|
||||||
|
try {
|
||||||
|
TokenRet tokenRet = TokenRet.fromJson(s);
|
||||||
|
List<String> skip = Collections.singletonList(ResultCode.CODE_ERROR_USER_SWITCH);
|
||||||
|
if (!skip.contains(tokenRet.getCode())) {
|
||||||
|
showResult(tokenRet.getCode(), tokenRet.getMsg(),null);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mAuthHelper=PhoneNumberAuthHelper.getInstance(mContext, mTokenResultListener);
|
||||||
|
mAuthHelper.getReporter().setLoggerEnable(jsonObject.getBooleanValue("isDebug"));
|
||||||
|
mAuthHelper.setAuthSDKInfo(jsonObject.getString("androidSk"));
|
||||||
|
|
||||||
|
// 授权页是否跟随系统深色模式
|
||||||
|
mAuthHelper.setAuthPageUseDayLight(jsonObject.getBooleanValue("authPageUseDayLight", false));
|
||||||
|
// 横屏水滴屏全屏适配
|
||||||
|
mAuthHelper.keepAuthPageLandscapeFullSreen(jsonObject.getBooleanValue("autoQuitPage", false));
|
||||||
|
// 用户控制返回键及左上角返回按钮效果, 是否自动退出授权页面,false时由用户自己控制
|
||||||
|
if (!jsonObject.getBooleanValue("autoQuitPage", false)) {
|
||||||
|
mAuthHelper.userControlAuthPageCancel();
|
||||||
|
}
|
||||||
|
// SDK内置所有界面隐藏底部导航栏
|
||||||
|
if (jsonObject.getBooleanValue("keepAllPageHideNavigationBar", false)) {
|
||||||
|
mAuthHelper.keepAllPageHideNavigationBar();
|
||||||
|
}
|
||||||
|
// 授权页物理返回键禁用
|
||||||
|
mAuthHelper.closeAuthPageReturnBack(jsonObject.getBooleanValue("closeAuthPageReturnBack", false));
|
||||||
|
/// 延时的情况下进行预取号,加快拉取授权页面
|
||||||
|
|
||||||
|
if (jsonObject.getBooleanValue("isDelay")) {
|
||||||
|
mAuthHelper.checkEnvAvailable(PhoneNumberAuthHelper.SERVICE_TYPE_LOGIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 延时登录操作
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
public void startLogin(int timeout){
|
||||||
|
if (sdkAvailable) {
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
getLoginToken(timeout);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "SDK环境检查未通过,无法拉起授权页");
|
||||||
|
showResult("600002", "SDK环境不可用,请检查网络和SIM卡", null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回默认上网卡运营商
|
||||||
|
* @param
|
||||||
|
* @return CMCC(移动)、CUCC(联通)、CTCC(电信)
|
||||||
|
*/
|
||||||
|
public String getCurrentCarrierName(){
|
||||||
|
return mAuthHelper.getCurrentCarrierName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进入app就需要登录的场景使用
|
||||||
|
*/
|
||||||
|
private void oneKeyLogin() {
|
||||||
|
mUIConfig.configAuthPage();
|
||||||
|
mAuthHelper.getLoginToken(mActivity, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在不是一进app就需要登录的场景 建议调用此接口 加速拉起一键登录页面
|
||||||
|
* 等到用户点击登录的时候 授权页可以秒拉
|
||||||
|
* 预取号的成功与否不影响一键登录功能,所以不需要等待预取号的返回。
|
||||||
|
* @param timeout
|
||||||
|
*/
|
||||||
|
private void accelerateLoginPage(int timeout) {
|
||||||
|
mAuthHelper.accelerateLoginPage(timeout, new PreLoginResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onTokenSuccess(String s) {
|
||||||
|
Log.e(TAG, "预取号成功: " + s);
|
||||||
|
showResult("600016", null, s);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onTokenFailed(String s, String s1) {
|
||||||
|
Log.e(TAG, "预取号失败:" + ", " + s1);
|
||||||
|
JSONObject jsonDataObj = new JSONObject();
|
||||||
|
jsonDataObj.put("name", s);
|
||||||
|
jsonDataObj.put("name1", s1);
|
||||||
|
showResult("600012", null, jsonDataObj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 拉起授权页
|
||||||
|
* @param timeout 超时时间
|
||||||
|
*/
|
||||||
|
public void getLoginToken(int timeout) {
|
||||||
|
try {
|
||||||
|
Log.i(TAG, "configAuthPage 开始配置授权页...");
|
||||||
|
mUIConfig.configAuthPage();
|
||||||
|
Log.i(TAG, "configAuthPage 配置完成");
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "configAuthPage 异常: " + e.getMessage(), e);
|
||||||
|
showResult("600002", "授权页配置异常: " + e.getMessage(), null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mTokenResultListener = new TokenResultListener() {
|
||||||
|
@Override
|
||||||
|
public void onTokenSuccess(String s) {
|
||||||
|
TokenRet tokenRet = TokenRet.fromJson(s);
|
||||||
|
try {
|
||||||
|
if (ResultCode.CODE_START_AUTHPAGE_SUCCESS.equals(tokenRet.getCode())) {
|
||||||
|
Log.i(TAG, "唤起授权页成功:" + s);
|
||||||
|
}
|
||||||
|
showResult(tokenRet.getCode(), tokenRet.getMsg(),tokenRet.getToken());
|
||||||
|
if (ResultCode.CODE_SUCCESS.equals(tokenRet.getCode())) {
|
||||||
|
Log.i(TAG, "获取token成功:" + s);
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTokenFailed(String s) {
|
||||||
|
Log.e(TAG, "获取token失败:" + s);
|
||||||
|
//如果环境检查失败 使用其他登录方式
|
||||||
|
try {
|
||||||
|
TokenRet tokenRet = TokenRet.fromJson(s);
|
||||||
|
showResult(tokenRet.getCode(), tokenRet.getMsg(),null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
// 失败时也不关闭
|
||||||
|
mAuthHelper.setAuthListener(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mAuthHelper.setAuthListener(mTokenResultListener);
|
||||||
|
mAuthHelper.getLoginToken(mActivity, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDK环境检查函数,检查终端是否⽀持号码认证,通过TokenResultListener返回code
|
||||||
|
* type 1:本机号码校验 2: ⼀键登录
|
||||||
|
* 600024 终端⽀持认证
|
||||||
|
* 600013 系统维护,功能不可⽤
|
||||||
|
*/
|
||||||
|
public void checkEnvAvailable(@IntRange(from = 1, to = 2) int type){
|
||||||
|
mAuthHelper.checkEnvAvailable(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取授权页协议勾选框选中状态
|
||||||
|
*/
|
||||||
|
public boolean queryCheckBoxIsChecked(){
|
||||||
|
return mAuthHelper.queryCheckBoxIsChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置授权页协议勾选框选中状态
|
||||||
|
*
|
||||||
|
* @param paramBoolean勾选框选中状态
|
||||||
|
*/
|
||||||
|
public boolean setCheckBoxIsChecked(){
|
||||||
|
mAuthHelper.setProtocolChecked(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退出授权页面
|
||||||
|
*/
|
||||||
|
public void quitPage(){
|
||||||
|
mAuthHelper.quitLoginPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束授权页loading dialog
|
||||||
|
*/
|
||||||
|
public void hideLoading(){
|
||||||
|
mAuthHelper.hideLoginLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理参数,对参数进行处理包含color、Path
|
||||||
|
* @param parmas
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private JSONObject formatParmas(Object parmas){
|
||||||
|
JSONObject formatData = JSONObject.parseObject(JSONObject.toJSONString(parmas));
|
||||||
|
for (Map.Entry<String, Object> entry : formatData.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
String keyLower = key.toLowerCase();
|
||||||
|
String strValue = formatData.getString(key);
|
||||||
|
|
||||||
|
// 判断是否是颜色代码
|
||||||
|
if (keyLower.contains("color") && strValue != null && strValue.contains("#")) {
|
||||||
|
try {
|
||||||
|
formatData.put(key, Color.parseColor(strValue));
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.w(TAG, "颜色解析失败: " + key + " = " + strValue, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 判断是否是路径字段(排除按钮状态背景 logBtnBackgroundPath)
|
||||||
|
else if (
|
||||||
|
!key.contains("logBtnBackgroundPath") &&
|
||||||
|
keyLower.contains("path") &&
|
||||||
|
strValue != null &&
|
||||||
|
!strValue.isEmpty() &&
|
||||||
|
!strValue.contains("http")
|
||||||
|
) {
|
||||||
|
formatData.put(key, UtilTool.flutterToPath(strValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对配置参数进行格式化并且转换
|
||||||
|
* @param jsonObject
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private AuthUIConfig.Builder getFormatConfig(JSONObject jsonObject){
|
||||||
|
AuthUIConfig.Builder config = JSON.parseObject(JSONObject.toJSONString(jsonObject), AuthUIConfig.Builder.class);
|
||||||
|
|
||||||
|
// 设置按钮的背景
|
||||||
|
// 20230518 修正错误 setLoadingBackgroundPath -> setLogBtnBackgroundPath
|
||||||
|
if (jsonObject.getString("logBtnBackgroundPath") != null && jsonObject.getString("logBtnBackgroundPath").contains(",")) {
|
||||||
|
config.setLogBtnBackgroundDrawable(UtilTool.getStateListDrawable(mContext, jsonObject.getString("logBtnBackgroundPath")));
|
||||||
|
} else {
|
||||||
|
config.setLogBtnBackgroundPath(UtilTool.flutterToPath(jsonObject.getString("logBtnBackgroundPath")));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* authPageActIn = var1;
|
||||||
|
* activityOut = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "authPageActIn") && UtilTool.dataStatus(jsonObject, "activityOut")){
|
||||||
|
config.setAuthPageActIn(jsonObject.getString("authPageActIn"), jsonObject.getString("activityOut"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* authPageActOut = var1;
|
||||||
|
* activityIn = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "authPageActOut") && UtilTool.dataStatus(jsonObject, "activityIn")){
|
||||||
|
config.setAuthPageActOut(jsonObject.getString("authPageActOut"), jsonObject.getString("activityIn"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* protocolOneName = var1;
|
||||||
|
* protocolOneURL = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "protocolOneName") && UtilTool.dataStatus(jsonObject, "protocolOneURL")){
|
||||||
|
config.setAppPrivacyOne(jsonObject.getString("protocolOneName"), jsonObject.getString("protocolOneURL"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* protocolTwoName = var1;
|
||||||
|
* protocolTwoURL = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "protocolTwoName") && UtilTool.dataStatus(jsonObject, "protocolTwoURL")){
|
||||||
|
config.setAppPrivacyTwo(jsonObject.getString("protocolTwoName"), jsonObject.getString("protocolTwoURL"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* protocolThreeName = var1;
|
||||||
|
* protocolThreeURL = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "protocolThreeName") && UtilTool.dataStatus(jsonObject, "protocolThreeURL")){
|
||||||
|
config.setAppPrivacyThree(jsonObject.getString("protocolThreeName"), jsonObject.getString("protocolThreeURL"));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* protocolColor = var1;
|
||||||
|
* protocolOneColor = var2;
|
||||||
|
* protocolTwoColor = var2;
|
||||||
|
* protocolThreeColor = var2;
|
||||||
|
*/
|
||||||
|
if(UtilTool.dataStatus(jsonObject, "protocolColor") && UtilTool.dataStatus(jsonObject, "protocolCustomColor")){
|
||||||
|
config.setAppPrivacyColor(jsonObject.getIntValue("protocolColor"), jsonObject.getIntValue("protocolCustomColor"));
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
package com.sean.rao.ali_auth.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
public class AppUtils extends com.nirvana.tools.core.AppUtils {
|
||||||
|
public static int dp2px(Context context, float dipValue) {
|
||||||
|
try {
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
return (int) (dipValue * scale + 0.5f);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return (int) dipValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int px2dp(Context context, float px) {
|
||||||
|
try {
|
||||||
|
final float scale = context.getResources().getDisplayMetrics().density;
|
||||||
|
return (int) (px / scale + 0.5f);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return (int) px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPhoneWidthPixels(Context context) {
|
||||||
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
DisplayMetrics var2 = new DisplayMetrics();
|
||||||
|
if (wm != null) {
|
||||||
|
wm.getDefaultDisplay().getMetrics(var2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return var2.widthPixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPhoneHeightPixels(Context context) {
|
||||||
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
DisplayMetrics var2 = new DisplayMetrics();
|
||||||
|
if (wm != null) {
|
||||||
|
wm.getDefaultDisplay().getMetrics(var2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return var2.heightPixels;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.sean.rao.ali_auth.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class ExecutorManager {
|
||||||
|
private static ExecutorService threadExecutor;
|
||||||
|
|
||||||
|
public static void run(Runnable var0) {
|
||||||
|
threadExecutor.execute(var0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
threadExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),
|
||||||
|
Runtime.getRuntime().availableProcessors(),
|
||||||
|
0, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.sean.rao.ali_auth.utils;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.os.Build;
|
||||||
|
import androidx.core.content.PermissionChecker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PermissionUtils {
|
||||||
|
@TargetApi(Build.VERSION_CODES.M)
|
||||||
|
public static void checkAndRequestPermissions(Activity context, int requestCode,
|
||||||
|
String... permissions) {
|
||||||
|
List<String> deniedPermissions = new ArrayList<>(permissions.length);
|
||||||
|
for(String permission:permissions) {
|
||||||
|
if(PermissionChecker.checkSelfPermission(context, permission) == PermissionChecker.PERMISSION_DENIED) {
|
||||||
|
deniedPermissions.add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!deniedPermissions.isEmpty()) {
|
||||||
|
String[] ps = new String[deniedPermissions.size()];
|
||||||
|
ps = deniedPermissions.toArray(ps);
|
||||||
|
context.requestPermissions(ps, requestCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,105 @@
|
|||||||
|
package com.sean.rao.ali_auth.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: ali_auth
|
||||||
|
* @Package: com.jokui.rao.auth.ali_auth
|
||||||
|
* @ClassName: StatusAll
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 2/16/22 5:58 PM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 2/16/22 5:58 PM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public enum StatusAll {
|
||||||
|
Status500000("参数获取异常!", "500000"),
|
||||||
|
Status500001("请先对插件进行监听!", "500001"),
|
||||||
|
Status500002("校验成功,可进行一键登录!", "500002"),
|
||||||
|
Status500003("该接口为延时登录接口,请先初始化后再次调用该接口!", "500003"),
|
||||||
|
Status500004("插件启动监听成功, 当前SDK版本: %s", "500004"),
|
||||||
|
Status600000("获取token成功!", "600000"),
|
||||||
|
Status600001("唤起授权页成功!", "600001"),
|
||||||
|
Status600002("唤起授权⻚失败!建议切换到其他登录⽅式", "600002"),
|
||||||
|
Status600004("获取运营商配置信息失败!创建⼯单联系⼯程师", "600004"),
|
||||||
|
Status600005("⼿机终端不安全!切换到其他登录⽅式", "600005"),
|
||||||
|
Status600007("未检测到sim卡!⽤户检查 SIM 卡后重试", "600007"),
|
||||||
|
Status600008("蜂窝⽹络未开启!⽤户开启移动⽹络后重试", "600008"),
|
||||||
|
Status600009("⽆法判断运营商! 创建⼯单联系⼯程师", "600009"),
|
||||||
|
Status600010("未知异常创建!⼯单联系⼯程师", "600010"),
|
||||||
|
Status600011("获取token失败!切换到其他登录⽅式", "600011"),
|
||||||
|
Status600012("预取号失败!", "600012"),
|
||||||
|
Status600013("运营商维护升级!该功能不可⽤创建⼯单联系⼯程师", "600013"),
|
||||||
|
Status600014("运营商维护升级!该功能已达最⼤调⽤次创建⼯单联系⼯程师", "600014"),
|
||||||
|
Status600015("接⼝超时!切换到其他登录⽅式", "600011"),
|
||||||
|
Status600016("预取号成功!", "600016"),
|
||||||
|
Status600017("AppID、Appkey解析失败! 秘钥未设置或者设置错误,请先检查秘钥信息,如果⽆法解决问题创建⼯单联系⼯程师", "600017"),
|
||||||
|
Status600018("请先初始化SDK!", "600018"),
|
||||||
|
Status600019("用户点击第三方按钮!", "600019"),
|
||||||
|
Status600021("点击登录时检测到运营商已切换!⽤户退出授权⻚,重新登录", "600021"),
|
||||||
|
Status600023("加载⾃定义控件异常!检查⾃定义控件添加是否正确", "600023"),
|
||||||
|
Status600024("终端环境检查⽀持认证", "600024"),
|
||||||
|
Status600025("终端检测参数错误检查传⼊参数类型与范围是否正确", "600025"),
|
||||||
|
Status600026("授权⻚已加载时不允许调⽤加速或预取号接⼝检查是否有授权⻚拉起后,去调⽤preLogin或者accelerateAuthPage的接⼝,该⾏为不允许", "600026"),
|
||||||
|
Status700000("用户取消登录", "700000"),
|
||||||
|
Status700001("用户切换其他登录方式", "700001"),
|
||||||
|
Status700002("用户点击登录按钮", "700002"),
|
||||||
|
Status700003("用户勾选协议选项", "700003"),
|
||||||
|
Status700004("用户点击协议富文本", "700004"),
|
||||||
|
Status700006("点击一键登录拉起授权页二次弹窗", "700006"),
|
||||||
|
Status700007("隐私协议二次弹窗关闭", "700007"),
|
||||||
|
Status700008("点击隐私协议二次弹窗上同意并继续", "700008"),
|
||||||
|
Status700009("点击隐私协议二次弹窗上的协议富文本文字", "700009"),
|
||||||
|
Status700010("中断页面消失时(suspendDisMissVC设置为YES时),点击左上角返回按钮透出的状态码", "700010"),
|
||||||
|
Status700020("授权页已销毁", "700020");
|
||||||
|
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构造方法
|
||||||
|
StatusAll(String name, String value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 普通方法
|
||||||
|
public static String getName(String value) {
|
||||||
|
for (StatusAll t : StatusAll.values()) {
|
||||||
|
if (t.getValue().equals(value)) {
|
||||||
|
return t.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 通过value取枚举
|
||||||
|
* @param valueKey
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static StatusAll getStatusByValue(String valueKey){
|
||||||
|
for (StatusAll enums : StatusAll.values()) {
|
||||||
|
if (enums.getValue().equals(valueKey)) {
|
||||||
|
return enums;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,161 @@
|
|||||||
|
package com.sean.rao.ali_auth.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.GradientDrawable;
|
||||||
|
import android.graphics.drawable.StateListDrawable;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.flutter.FlutterInjector;
|
||||||
|
import io.flutter.embedding.engine.loader.FlutterLoader;
|
||||||
|
import io.flutter.plugin.common.MethodCall;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ProjectName: android
|
||||||
|
* @Package: com.sean.rao.ali_auth.utils
|
||||||
|
* @ClassName: UtilTool
|
||||||
|
* @Description: java类作用描述
|
||||||
|
* @Author: liys
|
||||||
|
* @CreateDate: 5/11/22 3:33 PM
|
||||||
|
* @UpdateUser: 更新者
|
||||||
|
* @UpdateDate: 5/11/22 3:33 PM
|
||||||
|
* @UpdateRemark: 更新说明
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class UtilTool {
|
||||||
|
/**
|
||||||
|
* 判断数据类型
|
||||||
|
* @param data
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean dataStatus(JSONObject data, String key ){
|
||||||
|
if(data.containsKey(key) && data.get(key) != null){
|
||||||
|
if((data.get(key) instanceof Float) || (data.get(key) instanceof Double) && (double) data.get(key) > -1){
|
||||||
|
return true;
|
||||||
|
} else if((data.get(key) instanceof Integer) || (data.get(key) instanceof Number) && (int) data.get(key) > -1){
|
||||||
|
return true;
|
||||||
|
} else if((data.get(key) instanceof Boolean) && (boolean) data.get(key)){
|
||||||
|
return true;
|
||||||
|
} else if((data.get(key) instanceof String) && !((String) data.get(key)).equals("")){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flutter 路径转换
|
||||||
|
* @param fluPath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String flutterToPath(@Nullable Object fluPath){
|
||||||
|
FlutterLoader flutterLoader = FlutterInjector.instance().flutterLoader();
|
||||||
|
return flutterLoader.getLookupKeyForAsset(String.valueOf(fluPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取key
|
||||||
|
* @param call
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Object getValueByKey(MethodCall call, String key) {
|
||||||
|
if (call != null && call.hasArgument(key)) {
|
||||||
|
return call.argument(key);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建有状态的按钮
|
||||||
|
* @param mContext
|
||||||
|
* @param btnPathImage
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Drawable getStateListDrawable(Context mContext, String btnPathImage) {
|
||||||
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
|
if (!btnPathImage.contains(",")) {
|
||||||
|
return stateListDrawable;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
List<String> btnPathList = Arrays.asList(btnPathImage.split(","));
|
||||||
|
// 正常状态下的Drawable
|
||||||
|
BitmapDrawable drawable_p = getBitmapToBitmapDrawable(mContext, flutterToPath(btnPathList.get(0)));
|
||||||
|
// 按下和获取焦点是的Drawable
|
||||||
|
BitmapDrawable drawable_n = getBitmapToBitmapDrawable(mContext, flutterToPath(btnPathList.get(1)));
|
||||||
|
// 被禁用时的Drawable
|
||||||
|
BitmapDrawable drawable_b = getBitmapToBitmapDrawable(mContext, flutterToPath(btnPathList.get(2)));
|
||||||
|
|
||||||
|
stateListDrawable.addState(new int[]{android.R.attr.state_activated, android.R.attr.state_pressed}, drawable_n);
|
||||||
|
stateListDrawable.addState(new int[]{android.R.attr.state_activated, -android.R.attr.state_pressed}, drawable_p);
|
||||||
|
stateListDrawable.addState(new int[]{-android.R.attr.state_activated, -android.R.attr.state_pressed}, drawable_b);
|
||||||
|
stateListDrawable.addState(new int[]{-android.R.attr.state_activated, android.R.attr.state_pressed}, drawable_n);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.fillInStackTrace();
|
||||||
|
}
|
||||||
|
return stateListDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将bitmap数据转换为drawable
|
||||||
|
* @param mContext
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BitmapDrawable getBitmapToBitmapDrawable(Context mContext, String path) throws IOException {
|
||||||
|
// 正常状态下的Drawable
|
||||||
|
return new BitmapDrawable(mContext.getResources(), getPathToBitmap(mContext, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本地图片转换为bitmap
|
||||||
|
* @param mContext
|
||||||
|
* @param path
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Bitmap getPathToBitmap(Context mContext, String path) throws IOException {
|
||||||
|
AssetManager assetManager = mContext.getAssets();
|
||||||
|
InputStream fileDescriptor = assetManager.open(path);
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeStream(fileDescriptor);
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回数据封装
|
||||||
|
* @param code
|
||||||
|
* @param msg
|
||||||
|
* @param jsonDataObj
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static JSONObject resultFormatData(String code, @Nullable String msg, @Nullable Object jsonDataObj){
|
||||||
|
JSONObject jsonObj = new JSONObject();
|
||||||
|
jsonObj.put("code", code);
|
||||||
|
jsonObj.put("msg", msg != null && !msg.isEmpty() ? msg : StatusAll.getName(code));
|
||||||
|
jsonObj.put("data", jsonDataObj != null ? jsonDataObj : "");
|
||||||
|
jsonObj.put("isChecked", false);
|
||||||
|
return jsonObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,22 +0,0 @@
|
|||||||
package com.sean.rao.ali_auth
|
|
||||||
|
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
|
||||||
import io.flutter.plugin.common.MethodCall
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
|
|
||||||
class AliAuthPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
|
||||||
private lateinit var channel: MethodChannel
|
|
||||||
|
|
||||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
|
||||||
channel = MethodChannel(binding.binaryMessenger, "ali_auth")
|
|
||||||
channel.setMethodCallHandler(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
|
||||||
result.notImplemented()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
|
||||||
channel.setMethodCallHandler(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
8
airhub_app/packages/ali_auth/android/src/main/res/anim/in_activity.xml
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<translate
|
||||||
|
android:fromYDelta="100%"
|
||||||
|
android:toYDelta="0%"
|
||||||
|
android:duration="800"
|
||||||
|
/>
|
||||||
|
</set>
|
||||||
9
airhub_app/packages/ali_auth/android/src/main/res/anim/out_activity.xml
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<translate
|
||||||
|
android:duration="800"
|
||||||
|
android:fromYDelta="0%"
|
||||||
|
android:toYDelta="100%"
|
||||||
|
/>
|
||||||
|
</set>
|
||||||
|
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/colorPrimary" android:state_checked="true"/>
|
||||||
|
<item android:color="@color/colorPrimary" android:state_pressed="true"/>
|
||||||
|
<item android:color="@color/md_grey_700"/>
|
||||||
|
</selector>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:title="自定义协议页"
|
||||||
|
android:titleTextColor="@android:color/white"
|
||||||
|
tools:targetApi="lollipop" />
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:id="@+id/webView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/fly_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
</FrameLayout>
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:background="@color/navColor">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/btn_back"
|
||||||
|
android:layout_width="20dp"
|
||||||
|
android:layout_height="20dp"
|
||||||
|
android:background="@drawable/icon_close"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:cropToPadding="true"
|
||||||
|
android:layout_marginLeft="12dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:text="@string/custom_title"/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="50dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:background="@drawable/phone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="70dp"
|
||||||
|
android:text="@string/custom_slogan"
|
||||||
|
android:textColor="@color/black"
|
||||||
|
android:textSize="20sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_switch"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_marginTop="350dp"
|
||||||
|
android:text="@string/switch_msg"
|
||||||
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#3F51B5</color>
|
||||||
|
<color name="colorPrimaryDark">#303F9F</color>
|
||||||
|
<color name="colorAccent">#FF4081</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="md_grey_700">#616161</color>
|
||||||
|
<color name="white">#ffffffff</color>
|
||||||
|
<color name="navColor">#ff026ED2</color>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">号码认证Demo</string>
|
||||||
|
|
||||||
|
<string name="switch_msg">切换到短信登录页面</string>
|
||||||
|
<string name="custom_title">自定义标题</string>
|
||||||
|
<string name="custom_slogan">自定义Slogan</string>
|
||||||
|
<string name="custom_toast">同意服务条款才可以登录</string>
|
||||||
|
</resources>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<network-security-config>
|
||||||
|
<domain-config cleartextTrafficPermitted="true" >
|
||||||
|
<domain includeSubdomains="true">enrichgw.10010.com</domain> <!-- 联通内部5G请求域名,开发者需要添加 -->
|
||||||
|
<domain includeSubdomains="true">onekey.cmpassport.com</domain> <!-- 移动内部请求域名,开发者需要添加 -->
|
||||||
|
<domain includeSubdomains="true">140.205.57.248</domain> <!-- demo测试ip,开发者无需添加 -->
|
||||||
|
<domain includeSubdomains="true">gw.api.tbsandbox.com</domain> <!-- demo测试域名,开发者无需添加 -->
|
||||||
|
<domain includeSubdomains="true">m.aliyun.com</domain> <!-- demo测试域名,开发者无需添加 -->
|
||||||
|
</domain-config>
|
||||||
|
</network-security-config>
|
||||||
38
airhub_app/packages/ali_auth/ios/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.idea/
|
||||||
|
.vagrant/
|
||||||
|
.sconsign.dblite
|
||||||
|
.svn/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
profile
|
||||||
|
|
||||||
|
DerivedData/
|
||||||
|
build/
|
||||||
|
GeneratedPluginRegistrant.h
|
||||||
|
GeneratedPluginRegistrant.m
|
||||||
|
|
||||||
|
.generated/
|
||||||
|
|
||||||
|
*.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
|
||||||
|
!default.pbxuser
|
||||||
|
!default.mode1v3
|
||||||
|
!default.mode2v3
|
||||||
|
!default.perspectivev3
|
||||||
|
|
||||||
|
xcuserdata
|
||||||
|
|
||||||
|
*.moved-aside
|
||||||
|
|
||||||
|
*.pyc
|
||||||
|
*sync/
|
||||||
|
Icon?
|
||||||
|
.tags*
|
||||||
|
|
||||||
|
/Flutter/Generated.xcconfig
|
||||||
|
/Flutter/ephemeral/
|
||||||
|
/Flutter/flutter_export_environment.sh
|
||||||
0
airhub_app/packages/ali_auth/ios/Assets/.gitkeep
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 240 B |
|
After Width: | Height: | Size: 309 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 573 B |
|
After Width: | Height: | Size: 950 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
BIN
airhub_app/packages/ali_auth/ios/Assets/taobao.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
43
airhub_app/packages/ali_auth/ios/Classes/AliAuthEnum.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// AliAuthEnum.好的.h
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface AliAuthEnum : NSObject
|
||||||
|
+ (NSDictionary *)initData;
|
||||||
|
+ (NSDictionary *)keyPair;
|
||||||
|
@end
|
||||||
|
// FOUNDATION_EXPORT NSString * const StatusAll;
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, PNSBuildModelStyle) {
|
||||||
|
//全屏
|
||||||
|
PNSBuildModelStylePortrait,
|
||||||
|
PNSBuildModelStyleLandscape,
|
||||||
|
//PNSBuildModelStyleAutorotate,
|
||||||
|
|
||||||
|
//弹窗
|
||||||
|
PNSBuildModelStyleAlertPortrait,
|
||||||
|
PNSBuildModelStyleAlertLandscape,
|
||||||
|
// PNSBuildModelStyleAlertAutorotate,
|
||||||
|
|
||||||
|
//底部弹窗
|
||||||
|
PNSBuildModelStyleSheetPortrait,
|
||||||
|
|
||||||
|
//DIY 动画
|
||||||
|
PNSDIYAlertPortraitFade,
|
||||||
|
PNSDIYAlertPortraitDropDown,
|
||||||
|
// PNSDIYAlertPortraitBounce,
|
||||||
|
// PNSDIYPortraitFade,
|
||||||
|
// PNSDIYPortraitScale,
|
||||||
|
|
||||||
|
PNSBuildModelStyleGifBackground,
|
||||||
|
//other
|
||||||
|
PNSBuildModelStyleVideoBackground,
|
||||||
|
PNSBuildModelStylePicBackground,
|
||||||
|
};
|
||||||
|
|
||||||
129
airhub_app/packages/ali_auth/ios/Classes/AliAuthEnum.m
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// AliAuthEnum.m
|
||||||
|
// ali_auth
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AliAuthEnum.h"
|
||||||
|
|
||||||
|
@implementation AliAuthEnum : NSObject
|
||||||
|
static NSDictionary * StatusAll = nil;
|
||||||
|
+ (NSDictionary *)initData {
|
||||||
|
if (StatusAll == nil) {
|
||||||
|
StatusAll = @{
|
||||||
|
@"500000": @"参数获取异常!",
|
||||||
|
@"500001": @"密钥不能为空, 请先检查密钥是否设置!",
|
||||||
|
@"500002": @"校验成功,可进行一键登录!",
|
||||||
|
@"500003": @"该接口为延时登录接口,请先初始化后再次调用该接口!",
|
||||||
|
@"500004": @"插件启动监听成功, 当前SDK版本: %@",
|
||||||
|
@"600000": @"获取token成功!",
|
||||||
|
@"600001": @"唤起授权页成功!",
|
||||||
|
@"600002": @"唤起授权⻚失败!建议切换到其他登录⽅式",
|
||||||
|
@"600004": @"获取运营商配置信息失败!创建⼯单联系⼯程师",
|
||||||
|
@"600005": @"⼿机终端不安全!切换到其他登录⽅式",
|
||||||
|
@"600007": @"未检测到sim卡!⽤户检查 SIM 卡后,",
|
||||||
|
@"600008": @"蜂窝⽹络未开启!⽤户开启移动⽹络后重试",
|
||||||
|
@"600009": @"⽆法判断运营商! 创建⼯单联系⼯程师",
|
||||||
|
@"600010": @"未知异常创建!⼯单联系⼯程师",
|
||||||
|
@"600011": @"获取token失败!切换到其他登录⽅式",
|
||||||
|
@"600012": @"预取号失败!",
|
||||||
|
@"600013": @"运营商维护升级!该功能不可⽤创建⼯单联系⼯程师",
|
||||||
|
@"600014": @"运营商维护升级!该功能已达最⼤调⽤次创建⼯单联系⼯程师",
|
||||||
|
@"600015": @"接⼝超时!切换到其他登录⽅式",
|
||||||
|
@"600016": @"预取号成功!",
|
||||||
|
@"600017": @"AppID、Appkey解析失败! 秘钥未设置或者设置错误,请先检查秘钥信息,如果⽆法解决问题创建⼯单联系⼯程师",
|
||||||
|
@"600018": @"请先初始化SDK!",
|
||||||
|
@"600019": @"用户点击第三方按钮!",
|
||||||
|
@"600021": @"点击登录时检测到运营商已切换!⽤户退出授权⻚,重新登录",
|
||||||
|
@"600023": @"加载⾃定义控件异常!检查⾃定义控件添加是否正确",
|
||||||
|
@"600024": @"终端环境检查⽀持认证",
|
||||||
|
@"600025": @"终端检测参数错误检查传⼊参数类型与范围是否正确",
|
||||||
|
@"600026": @"授权⻚已加载时不允许调⽤加速或预取号接⼝检查是否有授权⻚拉起后,去调⽤preLogin或者accelerateAuthPage的接⼝,该⾏为不允许",
|
||||||
|
@"700000": @"用户取消登录",
|
||||||
|
@"700001": @"用户切换其他登录方式",
|
||||||
|
@"700002": @"用户点击登录按钮",
|
||||||
|
@"700003": @"用户勾选协议选项",
|
||||||
|
@"700004": @"用户点击协议富文本",
|
||||||
|
@"700006": @"点击一键登录拉起授权页二次弹窗",
|
||||||
|
@"700007": @"隐私协议二次弹窗关闭",
|
||||||
|
@"700008": @"点击隐私协议二次弹窗上同意并继续",
|
||||||
|
@"700009": @"点击隐私协议二次弹窗上的协议富文本文字",
|
||||||
|
@"700010": @"中断页面消失时(suspendDisMissVC设置为YES时),点击左上角返回按钮透出的状态码",
|
||||||
|
@"700020": @"授权页已销毁!",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return StatusAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSDictionary *)keyPair {
|
||||||
|
return @{
|
||||||
|
/// 1、状态栏
|
||||||
|
@"isStatusBarHidden": @"prefersStatusBarHidden",
|
||||||
|
@"lightColor": @"preferredStatusBarStyle",
|
||||||
|
/// 2、导航栏
|
||||||
|
@"navHidden": @"navIsHidden",
|
||||||
|
@"backgroundColor": @"alertContentViewColor",
|
||||||
|
@"navReturnImgPath": @"navBackImage",
|
||||||
|
@"navReturnHidden": @"hideNavBackItem",
|
||||||
|
/// 3、Logo
|
||||||
|
@"logoImgPath": @"logoImage",
|
||||||
|
@"logoHidden": @"logoIsHidden",
|
||||||
|
/// 4、Slogan
|
||||||
|
@"sloganHidden": @"sloganIsHidden",
|
||||||
|
/// 5、掩码栏
|
||||||
|
@"numberSize": @"numberFont",
|
||||||
|
/// 6、登录按钮
|
||||||
|
/// 7、切换到其他方式
|
||||||
|
@"switchAccHidden": @"changeBtnIsHidden",
|
||||||
|
@"switchAccText": @"changeBtnTitle",
|
||||||
|
/// 9、协议栏
|
||||||
|
@"checkboxHidden": @"checkBoxIsHidden",
|
||||||
|
@"checkBoxHeight": @"checkBoxWH",
|
||||||
|
@"privacyState": @"checkBoxIsChecked",
|
||||||
|
@"privacyTextSize": @"privacyFont",
|
||||||
|
@"protocolGravity": @"privacyAlignment",
|
||||||
|
@"protocolOwnOneColor": @"privacyOneColor",
|
||||||
|
@"protocolOwnTwoColor": @"privacyTwoColor",
|
||||||
|
@"protocolOwnThreeColor": @"privacyThreeColor",
|
||||||
|
@"protocolOwnColor": @"privacyOperatorColor",
|
||||||
|
@"privacyBefore": @"privacyPreText",
|
||||||
|
@"privacyEnd": @"privacySufText",
|
||||||
|
@"vendorPrivacyPrefix": @"privacyOperatorPreText",
|
||||||
|
@"vendorPrivacySuffix": @"privacyOperatorSufText",
|
||||||
|
@"privacyConectTexts": @"privacyConectTexts",
|
||||||
|
/// 协议详情
|
||||||
|
@"webNavColor": @"privacyNavColor",
|
||||||
|
@"webNavTextColor": @"privacyNavTitleColor",
|
||||||
|
@"webNavTextSize": @"privacyNavTitleFont",
|
||||||
|
@"webNavReturnImgPath": @"privacyNavBackImage",
|
||||||
|
///
|
||||||
|
@"pageBackgroundPath": @"backgroundImage",
|
||||||
|
/// 弹窗
|
||||||
|
@"dialogCornerRadiusArray": @"alertCornerRadiusArray",
|
||||||
|
@"alertCloseImagePath": @"alertCloseImage",
|
||||||
|
/// 二次
|
||||||
|
@"privacyAlertIsNeedAutoLogin": @"privacyAlertIsNeedAutoLogin",
|
||||||
|
@"privacyAlertTitleTextSize": @"privacyAlertTitleFont",
|
||||||
|
@"privacyAlertContentVerticalMargin": @"privacyAlertLineSpaceDp",
|
||||||
|
@"privacyAlertBtnText": @"privacyAlertBtnContent",
|
||||||
|
@"privacyAlertBtnTextSize": @"privacyAlertButtonFont",
|
||||||
|
@"privacyAlertContentTextSize": @"privacyAlertContentFont",
|
||||||
|
@"privacyAlertBtnBackgroundImgPath": @"privacyAlertBtnBackgroundImages",
|
||||||
|
@"privacyAlertCloseImagPath": @"privacyAlertCloseButtonImage",
|
||||||
|
@"privacyAlertCloseBtnShow": @"privacyAlertCloseButtonIsNeedShow",
|
||||||
|
@"privacyAlertBefore": @"privacyAlertPreText",
|
||||||
|
@"privacyAlertEnd": @"privacyAlertSufText",
|
||||||
|
@"privacyAlertProtocolNameUseUnderLine": @"privacyAlertContentUnderline",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark --枚举,消息提示框的位置
|
||||||
|
typedef NS_ENUM(NSInteger, MBProgressHUBPosition) {
|
||||||
|
MBProgressHUBPositionTop, //头部
|
||||||
|
MBProgressHUBPositionCenter, //中心
|
||||||
|
MBProgressHUBPositionBottom //底部
|
||||||
|
};
|
||||||
|
@end
|
||||||
|
|
||||||
5
airhub_app/packages/ali_auth/ios/Classes/AliAuthPlugin.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#import <Flutter/Flutter.h>
|
||||||
|
|
||||||
|
|
||||||
|
@interface AliAuthPlugin : NSObject<FlutterPlugin>
|
||||||
|
@end
|
||||||
683
airhub_app/packages/ali_auth/ios/Classes/AliAuthPlugin.m
Normal file
@ -0,0 +1,683 @@
|
|||||||
|
#import "AliAuthPlugin.h"
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#import "AliAuthEnum.h"
|
||||||
|
#import "MJExtension.h"
|
||||||
|
#import <ATAuthSDK/ATAuthSDK.h>
|
||||||
|
//#import "MBProgressHUD.h"
|
||||||
|
#import "PNSBuildModelUtils.h"
|
||||||
|
#import "NSDictionary+Utils.h"
|
||||||
|
#import "UIColor+Hex.h"
|
||||||
|
#import <AuthenticationServices/AuthenticationServices.h>
|
||||||
|
|
||||||
|
#define TX_SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height
|
||||||
|
#define TX_SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
|
||||||
|
|
||||||
|
bool bool_true = true;
|
||||||
|
bool bool_false = false;
|
||||||
|
|
||||||
|
// 打印长度比较大的字符串
|
||||||
|
//#define NSLog(format,...) printf("%s",[[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String])
|
||||||
|
|
||||||
|
/// 添加ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding 取消
|
||||||
|
/// authorizationController.delegate = self; authorizationController.presentationContextProvider = self; 警告信息
|
||||||
|
@interface AliAuthPlugin()<UIApplicationDelegate, FlutterStreamHandler, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
|
||||||
|
@property (nonatomic, strong) UINavigationController *navigationController;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AliAuthPlugin{
|
||||||
|
FlutterEventSink _eventSink;
|
||||||
|
FlutterResult _result;
|
||||||
|
FlutterMethodCall * _callData;
|
||||||
|
TXCustomModel * _model;
|
||||||
|
Boolean _isChecked;
|
||||||
|
Boolean _isHideToast;
|
||||||
|
}
|
||||||
|
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
|
||||||
|
AliAuthPlugin* instance = [[AliAuthPlugin alloc] init];
|
||||||
|
|
||||||
|
FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"ali_auth" binaryMessenger: [registrar messenger]];
|
||||||
|
FlutterEventChannel* chargingChannel = [FlutterEventChannel eventChannelWithName:@"ali_auth/event" binaryMessenger: [registrar messenger]];
|
||||||
|
|
||||||
|
[chargingChannel setStreamHandler: instance];
|
||||||
|
[registrar addMethodCallDelegate:instance channel: channel];
|
||||||
|
//为了让手机安装demo弹出使用网络权限弹出框
|
||||||
|
[[AliAuthPlugin alloc] httpAuthority];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - IOS 主动发送通知让 flutter调用监听 eventChannel start
|
||||||
|
- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
|
||||||
|
if (_eventSink == nil) {
|
||||||
|
_eventSink = eventSink;
|
||||||
|
/** 返回初始化状态 */
|
||||||
|
NSString *version = [[TXCommonHandler sharedInstance] getVersion];
|
||||||
|
|
||||||
|
NSDictionary *dict = @{ @"resultCode": @"500004", @"msg": version };
|
||||||
|
[self showResultMsg: dict msg:version];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (FlutterError*)onCancelWithArguments:(id)arguments {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
_eventSink = nil;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eventChannel end
|
||||||
|
#pragma mark - 测试联网阿里授权必须
|
||||||
|
-(void)httpAuthority{
|
||||||
|
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];//此处修改为自己公司的服务器地址
|
||||||
|
NSURLRequest *request = [NSURLRequest requestWithURL:url];
|
||||||
|
NSURLSession *session = [NSURLSession sharedSession];
|
||||||
|
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||||
|
if (error == nil) {
|
||||||
|
// NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
|
||||||
|
NSLog(@"联网成功!");
|
||||||
|
} else {
|
||||||
|
NSLog(@"联网失败!");
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
[dataTask resume];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - flutter调用 oc eventChannel start
|
||||||
|
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
|
||||||
|
// SDK 初始化
|
||||||
|
_callData = call;
|
||||||
|
_result = result;
|
||||||
|
if ([@"getPlatformVersion" isEqualToString:call.method]) {
|
||||||
|
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
|
||||||
|
}
|
||||||
|
else if ([@"getCurrentCarrierName" isEqualToString:call.method]) {
|
||||||
|
// 获取当前上网卡运营商名称,比如中国移动、中国电信、中国联通
|
||||||
|
result([TXCommonUtils getCurrentCarrierName]);
|
||||||
|
}
|
||||||
|
// 初始化SDK
|
||||||
|
else if ([@"initSdk" isEqualToString:call.method]) {
|
||||||
|
_isHideToast = [call.arguments boolValueForKey: @"isHideToast" defaultValue: NO];
|
||||||
|
if (_eventSink == nil) {
|
||||||
|
result(@{ @"code": @"500001", @"msg": @"请先对插件进行监听!" });
|
||||||
|
} else {
|
||||||
|
[self initSdk];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 延时登录获取非延时登录
|
||||||
|
else if ([@"login" isEqualToString:call.method]) {
|
||||||
|
if(_model == nil){
|
||||||
|
NSDictionary *dict = @{ @"resultCode": @"500003" };
|
||||||
|
[self showResult: dict];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self->_isChecked = [_callData.arguments boolValueForKey: @"privacyState" defaultValue: NO];
|
||||||
|
[self loginWithModel: _model complete:^{}];
|
||||||
|
}
|
||||||
|
else if ([@"checkEnvAvailable" isEqualToString:call.method]) {
|
||||||
|
[self checkVerifyEnable:call result:result];
|
||||||
|
}
|
||||||
|
else if ([@"queryCheckBoxIsChecked" isEqualToString:call.method]) {
|
||||||
|
BOOL status = [[TXCommonHandler sharedInstance] queryCheckBoxIsChecked];
|
||||||
|
result(@(status));
|
||||||
|
}
|
||||||
|
else if ([@"setCheckboxIsChecked" isEqualToString:call.method]) {
|
||||||
|
[[TXCommonHandler sharedInstance] setCheckboxIsChecked:YES];
|
||||||
|
result(@(bool_true));
|
||||||
|
}
|
||||||
|
else if ([@"checkCellularDataEnable" isEqualToString:call.method]) {
|
||||||
|
[self checkCellularDataEnable:call result:result];
|
||||||
|
}
|
||||||
|
else if ([@"preLogin" isEqualToString:call.method]) {
|
||||||
|
[self getPreLogin:call result:result];
|
||||||
|
}
|
||||||
|
else if ([@"quitPage" isEqualToString:call.method]) {
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:nil];
|
||||||
|
}
|
||||||
|
else if ([@"hideLoading" isEqualToString:call.method]) {
|
||||||
|
[[TXCommonHandler sharedInstance] hideLoginLoading];
|
||||||
|
}
|
||||||
|
else if ([@"appleLogin" isEqualToString:call.method]) {
|
||||||
|
[self handleAuthorizationAppleIDButtonPress:call result:result];
|
||||||
|
}
|
||||||
|
else if ([@"openPage" isEqualToString:call.method]) {
|
||||||
|
// 1.初始化flutter控制器,并指定路由 “home”,flutter中根据该路由标识显示对应的界面
|
||||||
|
FlutterViewController* flutterViewController = [
|
||||||
|
[FlutterViewController alloc] initWithProject:nil
|
||||||
|
initialRoute:[call.arguments stringValueForKey: @"pageRoute" defaultValue: @"/"]
|
||||||
|
nibName:nil
|
||||||
|
bundle:nil
|
||||||
|
];
|
||||||
|
// 2. 跳转
|
||||||
|
flutterViewController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||||
|
[[self findCurrentViewController] presentViewController:flutterViewController animated: YES completion:nil];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result(FlutterMethodNotImplemented);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 初始化SDK以及相关布局
|
||||||
|
- (void)initSdk {
|
||||||
|
NSDictionary *dic = _callData.arguments;
|
||||||
|
// _model = [TXCustomModel mj_objectWithKeyValues: dic];
|
||||||
|
if ([[dic stringValueForKey: @"iosSk" defaultValue: @""] isEqualToString:@""]) {
|
||||||
|
NSDictionary *dict = @{ @"resultCode": @"500000" };
|
||||||
|
[self showResult: dict];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NSString *secret = [dic stringValueForKey: @"iosSk" defaultValue: @""];
|
||||||
|
/** 不管是否延时登录都需要,先初始化model */
|
||||||
|
_model = [PNSBuildModelUtils buildModelWithStyle: dic target:self selector:@selector(btnClick:)];
|
||||||
|
//1. 初始化sdk,设置secret
|
||||||
|
[[TXCommonHandler sharedInstance] setAuthSDKInfo:secret complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
//2. 调用check接口检查及准备接口调用环境
|
||||||
|
[[TXCommonHandler sharedInstance] checkEnvAvailableWithAuthType:PNSAuthTypeLoginToken complete:^(NSDictionary * _Nullable checkDic) {
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[checkDic objectForKey:@"resultCode"]] == YES) {
|
||||||
|
NSDictionary *dict = @{ @"resultCode": @"600024" };
|
||||||
|
[self showResult: dict];
|
||||||
|
//3. 调用取号接口,加速授权页的弹起
|
||||||
|
[[TXCommonHandler sharedInstance] accelerateLoginPageWithTimeout: 5.0 complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
//4. 预取号成功后判断是否延时登录,否则立即登录
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == YES) {
|
||||||
|
if (![dic boolValueForKey: @"isDelay" defaultValue: NO]) {
|
||||||
|
[self loginWithModel: self->_model complete:^{}];
|
||||||
|
}
|
||||||
|
NSString *carrierNam = [TXCommonUtils getCurrentCarrierName];
|
||||||
|
NSDictionary *acceleDict = @{ @"resultCode": @"600016", @"data": carrierNam };
|
||||||
|
[self showResult: acceleDict];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[self showResult: resultDic];
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
NSMutableDictionary *result = [NSMutableDictionary dictionaryWithDictionary:checkDic];
|
||||||
|
[result setValue:@(bool_false) forKey: @"token"];
|
||||||
|
[self showResult: result];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** SDK 判断网络环境是否支持 */
|
||||||
|
- (void)checkVerifyEnable:(FlutterMethodCall*)call result:(FlutterResult)result {
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
[[TXCommonHandler sharedInstance] checkEnvAvailableWithAuthType:PNSAuthTypeLoginToken complete:^(NSDictionary * _Nullable resultDic) {
|
||||||
|
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
|
||||||
|
[dict setValue: [resultDic objectForKey:@"resultCode"] forKey: @"code"];
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
[dict setValue: @(bool_false) forKey: @"data"];
|
||||||
|
} else {
|
||||||
|
[[TXCommonHandler sharedInstance] accelerateLoginPageWithTimeout:5.0 complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
/// NSLog(@"为后面授权页拉起加个速,加速结果:%@", resultDic);
|
||||||
|
}];
|
||||||
|
// 中国移动支持2G/3G/4G、中国联通支持3G/4G、中国电信支持4G。 2G网络下认证失败率较高
|
||||||
|
// WiFi,4G,3G,2G,NoInternet等
|
||||||
|
// NSString *networktype = [[TXCommonUtils init] getNetworktype];
|
||||||
|
// // 中国移动,中国联通,中国电信等
|
||||||
|
// NSString *carrierName = [[TXCommonUtils init] getCurrentCarrierName];
|
||||||
|
// if( [carrierName isEqual:(@"中国移动")] && [networktype isEqual:(@"2G")] && [networktype isEqual:(@"3G")] && [networktype isEqual:(@"4G")] ){
|
||||||
|
// result(@(bool_true));
|
||||||
|
// } else if( [carrierName isEqual:(@"中国联通")] && [networktype isEqual:(@"3G")] && [networktype isEqual:(@"4G")]){
|
||||||
|
// result(@(bool_true));
|
||||||
|
// } else if( [carrierName isEqual:(@"中国电信")] && [networktype isEqual:(@"4G")]){
|
||||||
|
// result(@(bool_true));
|
||||||
|
// }
|
||||||
|
// result(@(bool_false));
|
||||||
|
[dict setValue: @"终端环境检查⽀持认证" forKey: @"msg"];
|
||||||
|
[dict setValue: @"600024" forKey: @"code"];
|
||||||
|
[dict setValue: @(bool_true) forKey: @"data"];
|
||||||
|
}
|
||||||
|
[self resultData: dict];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 检测是否开启蜂窝网络 */
|
||||||
|
- (void)checkCellularDataEnable:(FlutterMethodCall*)call result:(FlutterResult)result {
|
||||||
|
bool status = [TXCommonUtils checkDeviceCellularDataEnable];
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"code": @"1",
|
||||||
|
@"msg" : @"蜂窝网络检测",
|
||||||
|
@"data" : @(status)
|
||||||
|
};
|
||||||
|
result(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - action 选中第三方按钮时回调
|
||||||
|
- (void)btnClick: (UIGestureRecognizer *) sender {
|
||||||
|
UIButton *view = (UIButton *)sender;
|
||||||
|
NSInteger index = view.tag;
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"code": @"700005",
|
||||||
|
@"msg" : @"点击第三方登录按钮",
|
||||||
|
@"data" : [NSNumber numberWithInteger: index]
|
||||||
|
};
|
||||||
|
[self resultData: dict];
|
||||||
|
if (!self->_isChecked && !self->_isHideToast) {
|
||||||
|
NSDictionary *dic = self -> _callData.arguments;
|
||||||
|
// [self showToast: [dic stringValueForKey: @"toastText" defaultValue: @"请先阅读用户协议"]];
|
||||||
|
} else {
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated: YES complete:^(void) {}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 一键登录预取号
|
||||||
|
- (void)getPreLogin:(FlutterMethodCall*)call result:(FlutterResult)result{
|
||||||
|
[self accelerateLogin:_model call:call result:result complete:^{}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 函数名: accelerateLoginPageWithTimeout
|
||||||
|
* @brief 加速一键登录授权页弹起,防止调用 getLoginTokenWithTimeout:controller:model:complete: 等待弹起授权页时间过长
|
||||||
|
* @param timeout:接口超时时间,单位s,默认3.0s,值为0.0时采用默认超时时间
|
||||||
|
* @param complete 结果异步回调,成功时resultDic=@{resultCode:600000, msg:...},其他情况时"resultCode"值请参考PNSReturnCode
|
||||||
|
*/
|
||||||
|
#pragma mark - action 一键登录预取号
|
||||||
|
- (void)accelerateLogin:(TXCustomModel *)model call:(FlutterMethodCall*)call result:(FlutterResult)result complete:(void (^)(void))completion {
|
||||||
|
float timeout = 5.0; // self.tf_timeout.text.floatValue;
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
//1. 调用check接口检查及准备接口调用环境
|
||||||
|
[[TXCommonHandler sharedInstance] checkEnvAvailableWithAuthType:PNSAuthTypeLoginToken complete:^(NSDictionary * _Nullable resultDic) {
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSDictionary *dict = @{ @"resultCode": @"600024" };
|
||||||
|
[self showResult: dict];
|
||||||
|
|
||||||
|
//2. 调用取号接口,加速授权页的弹起
|
||||||
|
[[TXCommonHandler sharedInstance] accelerateLoginPageWithTimeout:timeout complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSDictionary *acceleDict = @{ @"resultCode": @"600016" };
|
||||||
|
[self showResult: acceleDict];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转Flutter混合原生view界面
|
||||||
|
-(void)handleSingleTap:(UITapGestureRecognizer *)sender{ //获得参数
|
||||||
|
NSLog(@"%@", @"我被点击了");
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - action 一键登录公共方法
|
||||||
|
- (void)loginWithModel:(TXCustomModel *)model complete:(void (^)(void))completion {
|
||||||
|
float timeout = 5.0; //self.tf_timeout.text.floatValue;
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
// UIWindow *window = [[UIApplication sharedApplication].delegate window];
|
||||||
|
// UIViewController * _vc = [[ViewController alloc] init];
|
||||||
|
// window.rootViewController = _vc;
|
||||||
|
|
||||||
|
UIViewController *_vc = [self findCurrentViewController];
|
||||||
|
|
||||||
|
// UIButton *pushFlutterNativePageButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||||
|
// pushFlutterNativePageButton.frame = CGRectMake(100, 300, 300, 100);
|
||||||
|
// [pushFlutterNativePageButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
|
||||||
|
// [pushFlutterNativePageButton setTitle:@"跳转到Flutter混合原生view界面" forState:UIControlStateNormal];
|
||||||
|
// [pushFlutterNativePageButton addTarget:self action:@selector(pushFlutterNativePage) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
// [_vc.view addSubview:pushFlutterNativePageButton];
|
||||||
|
|
||||||
|
// 每次登录时都设置没有登录状态
|
||||||
|
self->_isChecked = false;
|
||||||
|
|
||||||
|
//1. 调用check接口检查及准备接口调用环境
|
||||||
|
[[TXCommonHandler sharedInstance] checkEnvAvailableWithAuthType:PNSAuthTypeLoginToken complete:^(NSDictionary * _Nullable resultDic) {
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//2. 调用取号接口,加速授权页的弹起
|
||||||
|
[[TXCommonHandler sharedInstance] accelerateLoginPageWithTimeout:timeout complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//3. 调用获取登录Token接口,可以立马弹起授权页
|
||||||
|
// 关闭loading
|
||||||
|
// [MBProgressHUD hideHUDForView:_vc.view animated:YES];
|
||||||
|
[[TXCommonHandler sharedInstance] getLoginTokenWithTimeout:timeout controller:_vc model:model complete:^(NSDictionary * _Nonnull resultDic) {
|
||||||
|
NSString *code = [resultDic objectForKey:@"resultCode"];
|
||||||
|
// UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickAllScreen:)];
|
||||||
|
//
|
||||||
|
// UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _vc.view.bounds.size.width, _vc.view.bounds.size.height)];
|
||||||
|
//将手势添加到需要相应的view中去
|
||||||
|
[[weakSelf findCurrentViewController].view hitTest:CGPointMake(_vc.view.bounds.size.width, _vc.view.bounds.size.height) withEvent:nil];
|
||||||
|
// [[weakSelf findCurrentViewController].view addSubview:headerView];
|
||||||
|
|
||||||
|
// 当未勾选隐私协议时,弹出 Toast 提示
|
||||||
|
if ([PNSCodeLoginControllerClickLoginBtn isEqualToString:code] && !self->_isChecked) {
|
||||||
|
} else if ([PNSCodeSuccess isEqualToString:code]) {
|
||||||
|
bool autoQuitPage = [self->_callData.arguments boolValueForKey: @"autoQuitPage" defaultValue: YES];
|
||||||
|
// 登录成功后是否自动关闭页面
|
||||||
|
if (autoQuitPage) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:nil];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if ([PNSCodeLoginControllerClickChangeBtn isEqualToString:code]) {
|
||||||
|
// 通过switchCheck 参数动态控制 是否需要切换其他方式时需要勾选
|
||||||
|
NSDictionary *dic = self -> _callData.arguments;
|
||||||
|
if (!self->_isChecked && !self-> _isHideToast && [dic boolValueForKey: @"switchCheck" defaultValue: YES]) {
|
||||||
|
} else {
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:nil];
|
||||||
|
}
|
||||||
|
} else if ([PNSCodeLoginControllerClickCheckBoxBtn isEqualToString:code]) { // 点击同意协议
|
||||||
|
self->_isChecked = [[resultDic objectForKey:@"isChecked"] boolValue];
|
||||||
|
} else if ([PNSCodeLoginControllerClickCancel isEqualToString:code]) { // 取消
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:nil];
|
||||||
|
} else if ([PNSCodeCarrierChanged isEqualToString:code]) { // 切换运营商
|
||||||
|
[[TXCommonHandler sharedInstance] cancelLoginVCAnimated:YES complete:nil];
|
||||||
|
}
|
||||||
|
[weakSelf showResult:resultDic];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - toast
|
||||||
|
- (void)showToast:(NSString*) message {
|
||||||
|
// NSDictionary *dic = _callData.arguments;
|
||||||
|
// UIView *view = [self findCurrentViewController].view;
|
||||||
|
// MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo: view animated:YES];
|
||||||
|
// // Set the text mode to show only text.
|
||||||
|
// hud.mode = MBProgressHUDModeText;
|
||||||
|
// hud.label.text = NSLocalizedString(message, @"温馨提示");
|
||||||
|
// // 内边剧
|
||||||
|
// hud.margin = [dic floatValueForKey: @"toastPadding" defaultValue: 10];
|
||||||
|
// // 文本颜色
|
||||||
|
// hud.contentColor = [UIColor colorWithHex: [dic stringValueForKey: @"toastColor" defaultValue: @"#FFFFFF"] defaultValue: @"#FFFFFF"];
|
||||||
|
// // 弹窗背景
|
||||||
|
// hud.bezelView.color = [UIColor colorWithHex: [dic stringValueForKey: @"toastBackground" defaultValue: @"#000000"] defaultValue: @"#000000"];
|
||||||
|
// // 弹窗背景样式
|
||||||
|
// hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
|
||||||
|
//
|
||||||
|
// CGFloat offSetY = view.bounds.size.height / 2;
|
||||||
|
// NSString* toastPosition = [dic stringValueForKey: @"toastPositionMode" defaultValue: @"bottom"];
|
||||||
|
// if ([toastPosition isEqual: @"top"]) {
|
||||||
|
// CGFloat top = [dic floatValueForKey: @"toastMarginTop" defaultValue: 30.f];
|
||||||
|
// offSetY = - offSetY + view.window.safeAreaInsets.top + top;
|
||||||
|
// } else if ([toastPosition isEqual: @"bottom"]) {
|
||||||
|
// CGFloat bottom = [dic floatValueForKey: @"toastMarginBottom" defaultValue: 30.f];
|
||||||
|
// offSetY = offSetY - view.window.safeAreaInsets.bottom - bottom;
|
||||||
|
// } else if ([toastPosition isEqual: @"center"]) {
|
||||||
|
// offSetY = 0;
|
||||||
|
// }
|
||||||
|
// // 设置上下的位置
|
||||||
|
// hud.offset = CGPointMake(0.f, offSetY);
|
||||||
|
// [hud hideAnimated:YES afterDelay: [dic floatValueForKey: @"toastDelay" defaultValue: 3]];
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void) resultData:(NSDictionary *)dict{
|
||||||
|
if (_eventSink != nil) {
|
||||||
|
NSMutableDictionary *mutableDict = [dict mutableCopy];
|
||||||
|
[mutableDict setObject: self->_isChecked ? @(bool_true):@(bool_false) forKey: @"isChecked"];
|
||||||
|
_eventSink(mutableDict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 格式化数据utils返回数据
|
||||||
|
- (void)showResult:(id __nullable)showResult {
|
||||||
|
// 当存在autoHideLoginLoading时需要执行关闭
|
||||||
|
// if (![self->_callData.arguments boolValueForKey: @"autoHideLoginLoading" defaultValue: YES]) {
|
||||||
|
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
// [MBProgressHUD hideHUDForView: [self findCurrentViewController].view animated:YES];
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"code": [NSString stringWithFormat: @"%@", [showResult objectForKey:@"resultCode"]],
|
||||||
|
@"msg" : [AliAuthEnum initData][[showResult objectForKey:@"resultCode"]]?:@"",
|
||||||
|
@"data" : [showResult objectForKey: @"token"]?:@"",
|
||||||
|
@"isChecked": self->_isChecked ? @(bool_true):@(bool_false)
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: dict];
|
||||||
|
[self showResultLog: showResult];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 格式化数据utils返回数据
|
||||||
|
- (void)showResultMsg:(id __nullable)showResult msg: (NSString*)msg {
|
||||||
|
NSString *resultMsg = [NSString stringWithFormat: [AliAuthEnum initData][[showResult objectForKey:@"resultCode"]], msg]?:@"";
|
||||||
|
NSDictionary *dict = @{
|
||||||
|
@"code": [NSString stringWithFormat: @"%@", [showResult objectForKey:@"resultCode"]],
|
||||||
|
@"msg" : resultMsg,
|
||||||
|
@"data" : [showResult objectForKey: @"token"]?:@""
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: dict];
|
||||||
|
[self showResultLog: showResult];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 格式化数据utils统一输出日志
|
||||||
|
- (void)showResultLog:(id __nullable)showResult {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
NSString *desc = nil;
|
||||||
|
if ([showResult isKindOfClass:NSString.class]) {
|
||||||
|
desc = (NSString *)showResult;
|
||||||
|
} else {
|
||||||
|
desc = [showResult description];
|
||||||
|
// if (desc != nil) {
|
||||||
|
// desc = [NSString stringWithCString:[desc cStringUsingEncoding:NSUTF8StringEncoding] encoding:NSNonLossyASCIIStringEncoding];
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// NSLog( @"打印日志---->>%@", desc );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Apple授权登录
|
||||||
|
// 处理授权
|
||||||
|
- (void)handleAuthorizationAppleIDButtonPress:(FlutterMethodCall*)call result:(FlutterResult)result{
|
||||||
|
NSLog(@"点击授权---开始授权");
|
||||||
|
if (@available(iOS 13.0, *)) {
|
||||||
|
// 基于用户的Apple ID授权用户,生成用户授权请求的一种机制
|
||||||
|
ASAuthorizationAppleIDProvider *appleIDProvider = [[ASAuthorizationAppleIDProvider alloc] init];
|
||||||
|
// 创建新的AppleID 授权请求
|
||||||
|
ASAuthorizationAppleIDRequest *appleIDRequest = [appleIDProvider createRequest];
|
||||||
|
// 在用户授权期间请求的联系信息
|
||||||
|
appleIDRequest.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
|
||||||
|
// 由ASAuthorizationAppleIDProvider创建的授权请求 管理授权请求的控制器
|
||||||
|
ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest]];
|
||||||
|
// 设置授权控制器通知授权请求的成功与失败的代理
|
||||||
|
authorizationController.delegate = self;
|
||||||
|
// 设置提供 展示上下文的代理,在这个上下文中 系统可以展示授权界面给用户
|
||||||
|
authorizationController.presentationContextProvider = self;
|
||||||
|
// 在控制器初始化期间启动授权流
|
||||||
|
[authorizationController performRequests];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
// 处理不支持系统版本
|
||||||
|
NSLog(@"该系统版本不可用Apple登录");
|
||||||
|
NSDictionary *resultData = @{
|
||||||
|
@"code": @500,
|
||||||
|
@"msg" : @"该系统版本不可用Apple登录",
|
||||||
|
@"user" : @"",
|
||||||
|
@"familyName" : @"",
|
||||||
|
@"givenName" : @"",
|
||||||
|
@"email" : @"",
|
||||||
|
@"identityTokenStr": @"",
|
||||||
|
@"authorizationCodeStr": @""
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: resultData];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - delegate
|
||||||
|
//@optional 授权成功地回调
|
||||||
|
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)){
|
||||||
|
// NSLog(@"授权完成:::%@", authorization.credential);
|
||||||
|
NSLog(@"授权完成---开始返回数据");
|
||||||
|
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
|
||||||
|
// 用户登录使用ASAuthorizationAppleIDCredential
|
||||||
|
ASAuthorizationAppleIDCredential *appleIDCredential = (ASAuthorizationAppleIDCredential *)authorization.credential;
|
||||||
|
NSString *user = appleIDCredential.user;
|
||||||
|
// 使用过授权的,可能获取不到以下三个参数
|
||||||
|
NSString *familyName = appleIDCredential.fullName.familyName;
|
||||||
|
NSString *givenName = appleIDCredential.fullName.givenName;
|
||||||
|
NSString *email = appleIDCredential.email;
|
||||||
|
|
||||||
|
NSData *identityToken = appleIDCredential.identityToken;
|
||||||
|
NSData *authorizationCode = appleIDCredential.authorizationCode;
|
||||||
|
|
||||||
|
// 服务器验证需要使用的参数
|
||||||
|
NSString *identityTokenStr = [[NSString alloc] initWithData:identityToken encoding:NSUTF8StringEncoding];
|
||||||
|
NSString *authorizationCodeStr = [[NSString alloc] initWithData:authorizationCode encoding:NSUTF8StringEncoding];
|
||||||
|
// NSLog(@"后台参数--%@\n\n%@", identityTokenStr, authorizationCodeStr);
|
||||||
|
// NSLog(@"后台参数identityTokenStr---%@", identityTokenStr);
|
||||||
|
// NSLog(@"后台参数authorizationCodeStr---%@", authorizationCodeStr);
|
||||||
|
|
||||||
|
// Create an account in your system.
|
||||||
|
// For the purpose of this demo app, store the userIdentifier in the keychain.
|
||||||
|
// 需要使用钥匙串的方式保存用户的唯一信息
|
||||||
|
// [YostarKeychain save:KEYCHAIN_IDENTIFIER(@"userIdentifier") data:user];
|
||||||
|
// NSLog(@"user--%@", user);
|
||||||
|
// NSLog(@"familyName--%@", familyName);
|
||||||
|
// NSLog(@"givenName--%@", givenName);
|
||||||
|
// NSLog(@"email--%@", email);
|
||||||
|
|
||||||
|
NSDictionary *resultData = @{
|
||||||
|
@"code": @200,
|
||||||
|
@"msg" : @"获取成功",
|
||||||
|
@"user" : user,
|
||||||
|
@"familyName" : familyName != nil ? familyName : @"",
|
||||||
|
@"givenName" : givenName != nil ? givenName : @"",
|
||||||
|
@"email" : email != nil ? email : @"",
|
||||||
|
@"identityTokenStr": identityTokenStr,
|
||||||
|
@"authorizationCodeStr": authorizationCodeStr
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: resultData];
|
||||||
|
}else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]){
|
||||||
|
// 这个获取的是iCloud记录的账号密码,需要输入框支持iOS 12 记录账号密码的新特性,如果不支持,可以忽略
|
||||||
|
// Sign in using an existing iCloud Keychain credential.
|
||||||
|
// 用户登录使用现有的密码凭证
|
||||||
|
ASPasswordCredential *passwordCredential = (ASPasswordCredential*)authorization.credential;
|
||||||
|
// 密码凭证对象的用户标识 用户的唯一标识
|
||||||
|
NSString *user = passwordCredential.user;
|
||||||
|
// 密码凭证对象的密码
|
||||||
|
NSString *password = passwordCredential.password;
|
||||||
|
NSLog(@"user--%@", user);
|
||||||
|
NSLog(@"password--%@", password);
|
||||||
|
|
||||||
|
NSDictionary *resultData = @{
|
||||||
|
@"code": @200,
|
||||||
|
@"msg" : @"获取成功",
|
||||||
|
@"user" : user,
|
||||||
|
@"familyName" : @"",
|
||||||
|
@"givenName" : @"",
|
||||||
|
@"email" : @"",
|
||||||
|
@"identityTokenStr": @"",
|
||||||
|
@"authorizationCodeStr": @""
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: resultData];
|
||||||
|
}else{
|
||||||
|
NSLog(@"授权信息均不符");
|
||||||
|
NSDictionary *resultData = @{
|
||||||
|
@"code": @500,
|
||||||
|
@"msg" : @"授权信息均不符",
|
||||||
|
@"user" : @"",
|
||||||
|
@"familyName" : @"",
|
||||||
|
@"givenName" : @"",
|
||||||
|
@"email" : @"",
|
||||||
|
@"identityTokenStr": @"",
|
||||||
|
@"authorizationCodeStr": @""
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: resultData];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 授权失败的回调
|
||||||
|
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)){
|
||||||
|
// Handle error.
|
||||||
|
NSLog(@"苹果登录授权失败:%@", error);
|
||||||
|
NSString *errorMsg = nil;
|
||||||
|
switch (error.code) {
|
||||||
|
case ASAuthorizationErrorCanceled:
|
||||||
|
errorMsg = @"用户取消了授权请求";
|
||||||
|
break;
|
||||||
|
case ASAuthorizationErrorFailed:
|
||||||
|
errorMsg = @"授权请求失败";
|
||||||
|
break;
|
||||||
|
case ASAuthorizationErrorInvalidResponse:
|
||||||
|
errorMsg = @"授权请求响应无效";
|
||||||
|
break;
|
||||||
|
case ASAuthorizationErrorNotHandled:
|
||||||
|
errorMsg = @"未能处理授权请求";
|
||||||
|
break;
|
||||||
|
case ASAuthorizationErrorUnknown:
|
||||||
|
errorMsg = @"授权请求失败未知原因";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"%@", errorMsg);
|
||||||
|
NSDictionary *resultData = @{
|
||||||
|
@"code": @500,
|
||||||
|
@"msg" : errorMsg,
|
||||||
|
@"user" : @"",
|
||||||
|
@"familyName" : @"",
|
||||||
|
@"givenName" : @"",
|
||||||
|
@"email" : @"",
|
||||||
|
@"identityTokenStr": @"",
|
||||||
|
@"authorizationCodeStr": @""
|
||||||
|
};
|
||||||
|
|
||||||
|
[self resultData: resultData];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 告诉代理应该在哪个window 展示内容给用户
|
||||||
|
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
|
||||||
|
NSLog(@"88888888888");
|
||||||
|
// 返回window
|
||||||
|
return [UIApplication sharedApplication].windows.lastObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 获取到跟视图
|
||||||
|
- (UIViewController *)getRootViewController {
|
||||||
|
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
|
||||||
|
return window.rootViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark ======在view上添加UIViewController========
|
||||||
|
- (UIViewController *)findCurrentViewController{
|
||||||
|
UIWindow *window = [[UIApplication sharedApplication].delegate window];
|
||||||
|
|
||||||
|
// UIViewController * vc = [[ViewController alloc] init];
|
||||||
|
// window.rootViewController = vc;
|
||||||
|
// UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickAllScreen:)];
|
||||||
|
// [window addGestureRecognizer:singleTap];
|
||||||
|
UIViewController *topViewController = [window rootViewController];
|
||||||
|
while (true) {
|
||||||
|
if (topViewController.presentedViewController) {
|
||||||
|
topViewController = topViewController.presentedViewController;
|
||||||
|
} else if ([topViewController isKindOfClass:[UINavigationController class]] && [(UINavigationController*)topViewController topViewController]) {
|
||||||
|
topViewController = [(UINavigationController *)topViewController topViewController];
|
||||||
|
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
|
||||||
|
UITabBarController *tab = (UITabBarController *)topViewController;
|
||||||
|
topViewController = tab.selectedViewController;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) clickAllScreen:(UITapGestureRecognizer *) recognizer {
|
||||||
|
NSLog(@"点击事件屏蔽");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import Flutter
|
|
||||||
|
|
||||||
public class AliAuthPlugin: NSObject, FlutterPlugin {
|
|
||||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
|
||||||
let channel = FlutterMethodChannel(name: "ali_auth", binaryMessenger: registrar.messenger())
|
|
||||||
let instance = AliAuthPlugin()
|
|
||||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
|
|
||||||
result(FlutterMethodNotImplemented)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// PNSBaseNavigationController.h
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PNSBaseNavigationController : UINavigationController
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// PNSBaseNavigationController.m
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PNSBaseNavigationController.h"
|
||||||
|
|
||||||
|
@interface PNSBaseNavigationController ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PNSBaseNavigationController
|
||||||
|
|
||||||
|
- (BOOL)shouldAutorotate {
|
||||||
|
return [[self.viewControllers lastObject] shouldAutorotate];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||||
|
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
|
||||||
|
}
|
||||||
|
|
||||||
|
//- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
|
||||||
|
// return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
|
||||||
|
//}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// PNSBaseViewController.h
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PNSBaseViewController : UIViewController
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 负责初始化和设置controller里面的view,也就是self.view的subView。目的在于分类代码,所以与view初始化的相关代码都写在这里。
|
||||||
|
*
|
||||||
|
* @warning initSubviews只负责subviews的init,不负责布局。布局相关的代码应该写在 <b>viewDidLayoutSubviews</b>
|
||||||
|
*/
|
||||||
|
- (void)initSubviews NS_REQUIRES_SUPER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 负责布局controller里面的view,也就是self.view的subView。目的在于分类代码,所以与view初始化的相关代码都写在这里。
|
||||||
|
*
|
||||||
|
* @warning setLayoutSubviews只负责布局subviews的约束
|
||||||
|
*/
|
||||||
|
- (void)setLayoutSubviews;
|
||||||
|
|
||||||
|
/// 是否需要将状态栏改为浅色文字,默认为浅文字色
|
||||||
|
- (BOOL)shouldSetStatusBarStyleLight;
|
||||||
|
|
||||||
|
/// 是否影藏电池栏 (默认不影藏)
|
||||||
|
- (BOOL)shouldHiddenStatusBar;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// PNSBaseViewController.m
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PNSBaseViewController.h"
|
||||||
|
|
||||||
|
@interface PNSBaseViewController ()
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PNSBaseViewController
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
self.view.backgroundColor = [UIColor whiteColor];
|
||||||
|
|
||||||
|
[self initSubviews];
|
||||||
|
[self setLayoutSubviews];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
[super viewWillAppear:animated];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 状态栏
|
||||||
|
|
||||||
|
- (BOOL)prefersStatusBarHidden {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||||
|
return UIStatusBarStyleDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldSetStatusBarStyleLight {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldHiddenStatusBar {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UI
|
||||||
|
- (void)initSubviews {
|
||||||
|
// 子类重写
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setLayoutSubviews {
|
||||||
|
//子类重新
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - 屏幕方向(让设备支持旋转, 但是只支持竖屏, 这样防止从横屏过来导致APP没法旋转成竖屏)
|
||||||
|
// 是否支持设备自动旋转
|
||||||
|
- (BOOL)shouldAutorotate {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支持竖屏显示
|
||||||
|
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
|
||||||
|
return UIInterfaceOrientationMaskAllButUpsideDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)didReceiveMemoryWarning {
|
||||||
|
[super didReceiveMemoryWarning];
|
||||||
|
// Dispose of any resources that can be recreated.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
NSLog(@"[%@,%@]===已被释放",NSStringFromClass([self class]), self.navigationItem.title ?: self.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// NSDictionaryUtils.h
|
||||||
|
// UZEngine
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface NSDictionary (Utils)
|
||||||
|
- (NSInteger)integerValueForKey:(NSString *)key defaultValue:(NSInteger)defaultValue;
|
||||||
|
- (int)intValueForKey:(NSString *)key defaultValue:(int)defaultValue;
|
||||||
|
- (long long)longlongValueForKey:(NSString *)key defaultValue:(long long)defaultValue;
|
||||||
|
- (float)floatValueForKey:(NSString *)key defaultValue:(float)defaultValue;
|
||||||
|
- (BOOL)boolValueForKey:(NSString *)key defaultValue:(BOOL)defaultValue;
|
||||||
|
- (NSString *)stringValueForKey:(NSString *)key defaultValue:(NSString *)defaultValue;
|
||||||
|
- (NSArray *)arrayValueForKey:(NSString *)key defaultValue:(NSArray *)defaultValue;
|
||||||
|
- (NSDictionary *)dictValueForKey:(NSString *)key defaultValue:(NSDictionary *)defaultValue;
|
||||||
|
@end
|
||||||
124
airhub_app/packages/ali_auth/ios/Classes/NSDictionary+Utils.m
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// NSDictionary+Utils.m
|
||||||
|
// BCPay
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "NSDictionary+Utils.h"
|
||||||
|
|
||||||
|
@implementation NSDictionary (Utils)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 如果akey找不到,返回@"" (防止出现nil,使程序崩溃)
|
||||||
|
*
|
||||||
|
* @param aKey 字典key值
|
||||||
|
*
|
||||||
|
* @return 字典value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字典指定的key的数值字符
|
||||||
|
*
|
||||||
|
* @param key 需要取的键值
|
||||||
|
*
|
||||||
|
* @return value值如果为nil或者null会返回0字符串
|
||||||
|
*/
|
||||||
|
- (NSInteger)integerValueForKey:(NSString*)key defaultValue:(NSInteger)defaultValue {
|
||||||
|
if ([self valueForKeyIsNumber:key]) {
|
||||||
|
return [[self valueForKey:key] integerValue];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
- (int)intValueForKey:(NSString *)key defaultValue:(int)defaultValue{
|
||||||
|
if ([self valueForKeyIsNumber:key]) {
|
||||||
|
return [[self valueForKey:key] intValue];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
- (long long)longlongValueForKey:(NSString*)key defaultValue:(long long)defaultValue {
|
||||||
|
if ([self valueForKeyIsNumber:key]) {
|
||||||
|
return [[self valueForKey:key] longLongValue];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
- (float)floatValueForKey:(NSString*)key defaultValue:(float)defaultValue {
|
||||||
|
if ([self valueForKeyIsNumber:key]) {
|
||||||
|
return [[self valueForKey:key] floatValue];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)boolValueForKey:(NSString*)key defaultValue:(BOOL)defaultValue {
|
||||||
|
if ([self valueForKeyIsNumber:key]) {
|
||||||
|
return [[self valueForKey:key] boolValue];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)stringValueForKey:(NSString*)key defaultValue:(NSString*)defaultValue {
|
||||||
|
if ([self valueForKeyIsString:key]) {
|
||||||
|
return [self valueForKey:key];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *)arrayValueForKey:(NSString *)key defaultValue:(NSArray *)defaultValue {
|
||||||
|
if ([self valueForKeyIsArray:key]) {
|
||||||
|
return [self valueForKey:key];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)dictValueForKey:(NSString *)key defaultValue:(NSDictionary *)defaultValue {
|
||||||
|
if ([self valueForKeyIsNSDictionary:key]) {
|
||||||
|
return [self valueForKey:key];
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * @brief 替换 为空
|
||||||
|
// *
|
||||||
|
// * @param aKey 字典key值
|
||||||
|
// *
|
||||||
|
// * @return 字典value
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
//- (NSString *)replaceNBSPforKey:(id)aKey {
|
||||||
|
// NSString *value = [self objectForKey:aKey];
|
||||||
|
//
|
||||||
|
// if (!value) {
|
||||||
|
// value = @"";
|
||||||
|
// }
|
||||||
|
// NSString* str = [value stringByReplacingOccurrencesOfString:@" " withString:@" "] ;
|
||||||
|
//
|
||||||
|
// return [NSString stringWithFormat:@"%@",str];
|
||||||
|
//}
|
||||||
|
|
||||||
|
- (BOOL)valueForKeyIsArray:(NSString *)key {
|
||||||
|
return [self valueForKeyIsType:key type:[NSArray class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)valueForKeyIsString:(NSString *)key {
|
||||||
|
return [self valueForKeyIsType:key type:[NSString class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)valueForKeyIsNumber:(NSString *)key {
|
||||||
|
return [self valueForKeyIsType:key type:[NSNumber class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)valueForKeyIsNSDictionary:(NSString *)key {
|
||||||
|
return [self valueForKeyIsType:key type:[NSDictionary class]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)valueForKeyIsType:(NSString *)key type:(Class)kClass {
|
||||||
|
id value = [self objectForKey:key];
|
||||||
|
if (value == nil || [value isKindOfClass:[NSNull class]] || ![value isKindOfClass:kClass]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// PrivacyWebViewController.h
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PNSBaseViewController.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PrivacyWebViewController : PNSBaseViewController
|
||||||
|
|
||||||
|
- (instancetype)initWithUrl:(NSString *)url andUrlName:(NSString *)urlName;
|
||||||
|
|
||||||
|
/// 是否隐藏系统的导航栏
|
||||||
|
@property (nonatomic, assign) BOOL isHiddenNavgationBar;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
//
|
||||||
|
// PrivacyWebViewController.m
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "PrivacyWebViewController.h"
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
@interface PrivacyWebViewController ()<WKNavigationDelegate,WKUIDelegate>
|
||||||
|
|
||||||
|
@property (nonatomic, strong) WKWebView *webView;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSString *url;
|
||||||
|
|
||||||
|
@property (nonatomic, copy) NSString *urlName;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PrivacyWebViewController
|
||||||
|
|
||||||
|
- (instancetype)initWithUrl:(NSString *)url andUrlName:(nonnull NSString *)urlName{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_url = url ?: nil;
|
||||||
|
_urlName = urlName ?: nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
self.navigationItem.title = self.urlName ?: @"服务协议";
|
||||||
|
[self.view addSubview:self.webView];
|
||||||
|
|
||||||
|
if (self.url) {
|
||||||
|
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.url]]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillAppear:(BOOL)animated {
|
||||||
|
[super viewWillAppear:animated];
|
||||||
|
if (!self.isHiddenNavgationBar) {
|
||||||
|
//显示系统导航栏
|
||||||
|
[self.navigationController setNavigationBarHidden:NO animated:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidAppear:(BOOL)animated {
|
||||||
|
[super viewDidAppear:animated];
|
||||||
|
if (self.isHiddenNavgationBar) {
|
||||||
|
//隐藏系统导航栏
|
||||||
|
[self.navigationController setNavigationBarHidden:YES animated:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - UI
|
||||||
|
|
||||||
|
- (WKWebView *)webView {
|
||||||
|
if (!_webView) {
|
||||||
|
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
|
||||||
|
WKPreferences *preference = [[WKPreferences alloc]init];
|
||||||
|
preference.minimumFontSize = 0;
|
||||||
|
preference.javaScriptEnabled = YES;
|
||||||
|
preference.javaScriptCanOpenWindowsAutomatically = YES;
|
||||||
|
config.preferences = preference;
|
||||||
|
float y = self.navigationController.navigationBar.frame.size.height + [UIApplication sharedApplication].statusBarFrame.size.height;
|
||||||
|
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, y, self.view.frame.size.width, self.view.frame.size.height) configuration:config];
|
||||||
|
// 是否允许手势左滑返回上一级, 类似导航控制的左滑返回
|
||||||
|
_webView.allowsBackForwardNavigationGestures = YES;
|
||||||
|
_webView.navigationDelegate = self;
|
||||||
|
_webView.UIDelegate = self;
|
||||||
|
}
|
||||||
|
return _webView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initSubviews {
|
||||||
|
[super initSubviews];
|
||||||
|
[self.view addSubview:self.webView];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface CustomButton : UIButton
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
#import "CustomButton.h"
|
||||||
|
|
||||||
|
@implementation CustomButton
|
||||||
|
|
||||||
|
|
||||||
|
// title的位置
|
||||||
|
- (CGRect)titleRectForContentRect:(CGRect)contentRect {
|
||||||
|
/// CGFloat x, CGFloat y, CGFloat width, CGFloat height
|
||||||
|
return CGRectMake(0, self.bounds.size.height + 5, self.bounds.size.width, 16);
|
||||||
|
}
|
||||||
|
//背景图的位置
|
||||||
|
- (CGRect)backgroundRectForBounds:(CGRect)bounds{
|
||||||
|
return CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
|
||||||
|
}
|
||||||
|
@end
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// PNSBuildModelUtils.h
|
||||||
|
// ATAuthSceneDemo
|
||||||
|
//
|
||||||
|
// Created by Yau的MacBook on 2022/5/19.
|
||||||
|
// Copyright © 2022 Yau的MacBook. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <ATAuthSDK/ATAuthSDK.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PNSBuildModelUtils : NSObject
|
||||||
|
|
||||||
|
+ (TXCustomModel *)buildModelWithStyle:(NSDictionary *)dict
|
||||||
|
target:(id)target
|
||||||
|
selector:(SEL)selector;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
2332
airhub_app/packages/ali_auth/ios/Classes/Utils/PNSBuildModelUtils.m
Normal file
20
airhub_app/packages/ali_auth/ios/Classes/Utils/UIColor+Hex.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// UIColor+Hex.h
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Yau on 2023/4/13.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
#ifndef UIColor_Hex_h
|
||||||
|
#define UIColor_Hex_h
|
||||||
|
|
||||||
|
@interface UIColor (Hex)
|
||||||
|
+ (UIColor*)colorWithHex:(NSString *)hex defaultValue:(NSString *)defaultValue;
|
||||||
|
+ (UIColor*)colorWithHexString:(NSString *)hex alpha: (CGFloat)opacity defaultValue:(UIColor *)defaultValue;
|
||||||
|
+ (UIColor*)colorWithAlphaHex:(NSInteger)hex alpha: (CGFloat)opacity defaultValue:(UIColor *)defaultValue;
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif /* UIColor_Hex_h */
|
||||||
83
airhub_app/packages/ali_auth/ios/Classes/Utils/UIColor+Hex.m
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// UIColor+Hex.m
|
||||||
|
// ali_auth
|
||||||
|
//
|
||||||
|
// Created by Yau on 2023/4/13.
|
||||||
|
//
|
||||||
|
#import "UIColor+Hex.h"
|
||||||
|
|
||||||
|
@implementation UIColor (Hex)
|
||||||
|
+ (UIColor*)colorWithHex:(NSString*)hexColor defaultValue:(NSString*)defaultValue {
|
||||||
|
if (
|
||||||
|
hexColor == nil || [hexColor isEqual: @""]
|
||||||
|
) {
|
||||||
|
hexColor = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hexColor.length < 8) {
|
||||||
|
return [self colorWithHexString: hexColor alpha: 1 defaultValue: [UIColor blueColor]];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int alpha, red, green, blue;
|
||||||
|
NSRange range;
|
||||||
|
range.length =2;
|
||||||
|
|
||||||
|
range.location =1;
|
||||||
|
[[NSScanner scannerWithString:[hexColor substringWithRange:range]]scanHexInt:&alpha];//透明度
|
||||||
|
range.location =3;
|
||||||
|
[[NSScanner scannerWithString:[hexColor substringWithRange:range]]scanHexInt:&red];
|
||||||
|
range.location =5;
|
||||||
|
[[NSScanner scannerWithString:[hexColor substringWithRange:range]]scanHexInt:&green];
|
||||||
|
range.location =7;
|
||||||
|
[[NSScanner scannerWithString:[hexColor substringWithRange:range]]scanHexInt:&blue];
|
||||||
|
return [UIColor colorWithRed:(float)(red/255.0f)green:(float)(green/255.0f)blue:(float)(blue/255.0f)alpha:(float)(alpha/255.0f)];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
16进制颜色转换为UIColor
|
||||||
|
@param hexColor 16进制字符串(可以以0x开头,可以以#开头,也可以就是6位的16进制)
|
||||||
|
@param opacity 透明度
|
||||||
|
@return 16进制字符串对应的颜色
|
||||||
|
*/
|
||||||
|
+(UIColor *)colorWithHexString:(NSString *)hexColor alpha:(CGFloat)opacity defaultValue:(UIColor*)defaultValue{
|
||||||
|
NSString * cString = [[hexColor stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
|
||||||
|
|
||||||
|
|
||||||
|
// String should be 6 or 8 characters
|
||||||
|
if ([cString length] < 6) return [UIColor blackColor];
|
||||||
|
|
||||||
|
// strip 0X if it appears
|
||||||
|
if ([cString hasPrefix:@"0X"]) cString = [cString substringFromIndex:2];
|
||||||
|
if ([cString hasPrefix:@"#"]) cString = [cString substringFromIndex:1];
|
||||||
|
|
||||||
|
if ([cString length] != 6) return [UIColor blackColor];
|
||||||
|
|
||||||
|
// Separate into r, g, b substrings
|
||||||
|
NSRange range;
|
||||||
|
range.location = 0;
|
||||||
|
range.length = 2;
|
||||||
|
NSString * rString = [cString substringWithRange:range];
|
||||||
|
|
||||||
|
range.location = 2;
|
||||||
|
NSString * gString = [cString substringWithRange:range];
|
||||||
|
|
||||||
|
range.location = 4;
|
||||||
|
NSString * bString = [cString substringWithRange:range];
|
||||||
|
|
||||||
|
// Scan values
|
||||||
|
unsigned int r, g, b;
|
||||||
|
[[NSScanner scannerWithString:rString] scanHexInt:&r];
|
||||||
|
[[NSScanner scannerWithString:gString] scanHexInt:&g];
|
||||||
|
[[NSScanner scannerWithString:bString] scanHexInt:&b];
|
||||||
|
|
||||||
|
return [UIColor colorWithRed:((float)r / 255.0f)
|
||||||
|
green:((float)g / 255.0f)
|
||||||
|
blue:((float)b / 255.0f)
|
||||||
|
alpha:opacity];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (UIColor *)colorWithAlphaHex:(NSInteger)hex alpha:(CGFloat)alpha defaultValue:(UIColor*)defaultValue{
|
||||||
|
return [UIColor colorWithRed:((float)((hex & 0xFF0000) >> 16))/255.0 green:((float)((hex & 0xFF00) >> 8))/255.0 blue:((float)(hex & 0xFF))/255.0 alpha:alpha];
|
||||||
|
}
|
||||||
|
@end
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface PNSBackgroundView : UIView
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSURL *gifUrl;
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSURL *videoUrl;
|
||||||
|
|
||||||
|
- (void)show;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
#import "PNSBackgroundView.h"
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#import "UIImageView+WebCache.h"
|
||||||
|
|
||||||
|
@interface PNSBackgroundView ()
|
||||||
|
@property (nonatomic, strong) UIImageView *imgView;
|
||||||
|
@property (nonatomic, strong) AVPlayerLayer *playerLayer;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation PNSBackgroundView
|
||||||
|
|
||||||
|
- (void)show {
|
||||||
|
// 构建 GIF 背景
|
||||||
|
self.imgView = [self buildGIFViewWithUrl:self.gifUrl color:UIColor.blackColor];
|
||||||
|
if (self.imgView) {
|
||||||
|
[self addSubview:self.imgView];
|
||||||
|
}
|
||||||
|
// 构建 video 背景
|
||||||
|
self.playerLayer = [self buildVideoViewWithUrl:self.videoUrl color:UIColor.blackColor];
|
||||||
|
if (self.playerLayer) {
|
||||||
|
//设置 session 防止切断系统其他声音
|
||||||
|
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];
|
||||||
|
[self.layer addSublayer:self.playerLayer];
|
||||||
|
[self.playerLayer.player play]; //开始播放
|
||||||
|
//注册播放完通知,实现循环播放
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(playbackFinished:)
|
||||||
|
name:AVPlayerItemDidPlayToEndTimeNotification
|
||||||
|
object:self.playerLayer.player.currentItem];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)playbackFinished:(NSNotification *)notification {
|
||||||
|
[self.playerLayer.player seekToTime:CMTimeMake(0, 1)];
|
||||||
|
[self.playerLayer.player play];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews {
|
||||||
|
[super layoutSubviews];
|
||||||
|
self.playerLayer.frame = self.bounds;
|
||||||
|
self.imgView.frame = self.bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImageView *)buildGIFViewWithUrl:(NSURL *)url color:(UIColor *)color {
|
||||||
|
if (url == nil) { return nil; }
|
||||||
|
UIImageView *view = [[UIImageView alloc] init];
|
||||||
|
view.contentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
[view sd_setImageWithURL:url];
|
||||||
|
if (color) {
|
||||||
|
view.backgroundColor = color;
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (AVPlayerLayer *)buildVideoViewWithUrl:(NSURL *)url color:(UIColor *)color {
|
||||||
|
if (url == nil) { return nil; }
|
||||||
|
AVPlayerItem *playerItem = [[AVPlayerItem alloc] initWithURL:url];
|
||||||
|
AVPlayer *player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
|
||||||
|
player.muted = YES;
|
||||||
|
AVPlayerLayer *playLayer = [AVPlayerLayer playerLayerWithPlayer:player];
|
||||||
|
playLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||||
|
if (color) {
|
||||||
|
playLayer.backgroundColor = color.CGColor;
|
||||||
|
}
|
||||||
|
return playLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -1,13 +1,42 @@
|
|||||||
|
#
|
||||||
|
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
|
||||||
|
#
|
||||||
Pod::Spec.new do |s|
|
Pod::Spec.new do |s|
|
||||||
s.name = 'ali_auth'
|
s.name = 'ali_auth'
|
||||||
s.version = '1.3.7'
|
s.version = '1.3.7'
|
||||||
s.summary = 'Alibaba Cloud phone auth plugin for Flutter.'
|
s.summary = 'A new flutter plugin project.'
|
||||||
s.homepage = 'https://github.com/CodeGather/flutter_ali_auth'
|
s.description = <<-DESC
|
||||||
s.license = { :type => 'MIT' }
|
是一个集成阿里云号码认证服务SDK的flutter插件
|
||||||
s.author = { 'sean' => 'author@example.com' }
|
DESC
|
||||||
s.source = { :http => 'https://github.com/CodeGather/flutter_ali_auth' }
|
s.homepage = 'http://ki5k.com'
|
||||||
|
s.license = { :file => '../LICENSE' }
|
||||||
|
s.author = { 'Your Company' => 'raohong07@163.com' }
|
||||||
|
s.source = { :path => '.' }
|
||||||
s.source_files = 'Classes/**/*'
|
s.source_files = 'Classes/**/*'
|
||||||
|
s.public_header_files = 'Classes/**/*.h'
|
||||||
|
|
||||||
s.dependency 'Flutter'
|
s.dependency 'Flutter'
|
||||||
s.platform = :ios, '13.0'
|
s.dependency 'SDWebImage'
|
||||||
s.swift_version = '5.0'
|
s.dependency 'MJExtension'
|
||||||
|
# s.dependency 'MBProgressHUD'
|
||||||
|
|
||||||
|
s.frameworks = 'Network'
|
||||||
|
|
||||||
|
s.vendored_frameworks = 'libs/ATAuthSDK.framework', 'libs/YTXMonitor.framework', 'libs/YTXOperators.framework'
|
||||||
|
s.static_framework = false
|
||||||
|
|
||||||
|
# 解决移动crash
|
||||||
|
s.xcconfig = {
|
||||||
|
'OTHER_LDFLAGS' => '-ObjC',
|
||||||
|
'ENABLE_BITCODE' => 'NO'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 加载静态资源
|
||||||
|
s.resources = ['Assets/*']
|
||||||
|
|
||||||
|
s.ios.deployment_target = '11.0'
|
||||||
|
# s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
|
||||||
|
s.pod_target_xcconfig = {'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
|
||||||
|
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||