提交 403f3632 authored 作者: 史晓晨's avatar 史晓晨

init_temp

上级
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
*.iml
*.ipr
*.iws
.idea/
.vscode/
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: 18a827f3933c19f51862dde3fa472197683249d6
channel: stable
project_type: plugin
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 18a827f3933c19f51862dde3fa472197683249d6
base_revision: 18a827f3933c19f51862dde3fa472197683249d6
- platform: android
create_revision: 18a827f3933c19f51862dde3fa472197683249d6
base_revision: 18a827f3933c19f51862dde3fa472197683249d6
- platform: ios
create_revision: 18a827f3933c19f51862dde3fa472197683249d6
base_revision: 18a827f3933c19f51862dde3fa472197683249d6
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
## 0.0.1
* TODO: Describe initial release.
TODO: Add your license here.
# account_center
userSystem-AccountCenter.
## Getting Started
This project is a starting point for a Flutter
[plug-in package](https://flutter.dev/developing-packages/),
a specialized package that includes platform-specific implementation code for
Android and/or iOS.
For help getting started with Flutter development, view the
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
include: package:flutter_lints/flutter.yaml
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
linter:
rules:
prefer_const_constructors: false
prefer_const_literals_to_create_immutables: false
\ No newline at end of file
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.cxx
group 'com.clx.account_center'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.8.10'
repositories {
maven { setUrl("https://maven.aliyun.com/repository/central") }
maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
maven { setUrl("https://maven.aliyun.com/repository/google") }
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
maven { setUrl("https://maven.aliyun.com/repository/public") }
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
maven { setUrl("https://maven.aliyun.com/repository/central") }
maven { setUrl("https://maven.aliyun.com/repository/jcenter") }
maven { setUrl("https://maven.aliyun.com/repository/google") }
maven { setUrl("https://maven.aliyun.com/repository/gradle-plugin") }
maven { setUrl("https://maven.aliyun.com/repository/public") }
google()
mavenCentral()
}
// flatDir {
// dirs project(':aliyun_face_plugin').file('libs')
// }
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 31
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// packagingOptions {
// /// 阿里和pdf插件 so库冲突
// pickFirst "lib/arm64-v8a/libc++_shared.so"
// pickFirst "lib/armeabi-v7a/libc++_shared.so"
// }
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 19
}
viewBinding {
enabled = true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'pub.devrel:easypermissions:3.0.0'
// compile('pub.devrel:easypermissions:1.1.2') {
// exclude group: 'com.android.support'
// }
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'account_center'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.clx.account_center">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 必要权限,安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!--拨打电话权限-->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--允许获取粗略位置,粗略定位必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:usesCleartextTraffic="true"
>
<activity
android:theme="@style/AppTheme"
android:name="com.clx.account_center.H5Activity"
android:exported="true">
<!-- 深度链接配置 -->
</activity>
</application>
</manifest>
package com.clx.account_center;
import android.util.Log;
public class LogUtil {
static String className;//类名
static String methodName;//方法名
static int lineNumber;//行数
private LogUtil() {
/* Protect from instantiations */
}
public static boolean isDebuggable() {
return true;
}
private static String createLog(String log) {
StringBuffer buffer = new StringBuffer();
buffer.append(methodName);
buffer.append("(").append(className).append(":").append(lineNumber).append(") ");
buffer.append(log);
return buffer.toString();
}
private static void getMethodNames(StackTraceElement[] sElements) {
className = sElements[1].getFileName();
methodName = sElements[1].getMethodName();
lineNumber = sElements[1].getLineNumber();
}
public static void e(String message) {
if (!isDebuggable())
return;
// Throwable instance must be created before any methods
getMethodNames(new Throwable().getStackTrace());
Log.e(className, createLog(message));
}
public static void i(String message) {
if (!isDebuggable())
return;
getMethodNames(new Throwable().getStackTrace());
Log.i(className, createLog(message));
}
public static void d(String message) {
if (!isDebuggable())
return;
getMethodNames(new Throwable().getStackTrace());
Log.d(className, createLog(message));
}
public static void v(String message) {
if (!isDebuggable())
return;
getMethodNames(new Throwable().getStackTrace());
Log.v(className, createLog(message));
}
public static void w(String message) {
if (!isDebuggable())
return;
getMethodNames(new Throwable().getStackTrace());
Log.w(className, createLog(message));
}
public static void wtf(String message) {
if (!isDebuggable())
return;
getMethodNames(new Throwable().getStackTrace());
Log.wtf(className, createLog(message));
}
public static String getErrLog(String log){
getMethodNames(new Throwable().getStackTrace());
return createLog(log);
}
}
\ No newline at end of file
package com.clx.account_center;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import static android.app.Activity.RESULT_OK;
public class WBH5FaceVerifySDK {
//没有网络连接
private static final String NETWORK_NONE = "NETWORK_NONE";
//wifi连接
private static final String NETWORK_WIFI = "NETWORK_WIFI";
//手机网络数据连接类型
private static final String NETWORK_2G = "NETWORK_2G";
private static final String NETWORK_3G = "NETWORK_3G";
private static final String NETWORK_4G = "NETWORK_4G";
private static final String NETWORK_MOBILE = "NETWORK_MOBILE";
public static final int VIDEO_REQUEST = 0x0011;
public static final int WRITE_REQUEST = 0x0012;
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> mUploadCallbackAboveL;
private static WBH5FaceVerifySDK instance;
public static synchronized WBH5FaceVerifySDK getInstance() {
if (null == instance) {
instance = new WBH5FaceVerifySDK();
}
return instance;
}
private WBH5FaceVerifySDK() {
}
/**
* webView的websetting设置,ua配置一定不能少
* @param mWebView
* @param context
*/
public void setWebViewSettings(WebView mWebView, Context context) {
if (null == mWebView)
return;
WebSettings webSetting = mWebView.getSettings();
webSetting.setJavaScriptEnabled(true);
webSetting.setTextZoom(100);
webSetting.setAllowFileAccess(true);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSetting.setSupportZoom(true);
webSetting.setBuiltInZoomControls(true);
webSetting.setUseWideViewPort(true);
webSetting.setSupportMultipleWindows(false);
webSetting.setLoadWithOverviewMode(true);
// webSetting.setAppCacheEnabled(true);
webSetting.setDatabaseEnabled(true);
webSetting.setDomStorageEnabled(true);
// webSetting.setAppCacheMaxSize(Long.MAX_VALUE);
// webSetting.setAppCachePath(context.getDir("appcache", 0).getPath());
webSetting.setDatabasePath(context.getDir("databases", 0).getPath());
webSetting.setPluginState(WebSettings.PluginState.ON_DEMAND);
webSetting.setRenderPriority(WebSettings.RenderPriority.HIGH);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
webSetting.setAllowUniversalAccessFromFileURLs(true);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
}
String ua = webSetting.getUserAgentString();
webSetting.setUserAgentString(ua + ";kyc/h5face;kyc/2.0");//这个设置ua包含;kyc/h5face;kyc/2.0一定不能少
webSetting.setMediaPlaybackRequiresUserGesture(false);
}
/**
* 传统录制模式,将录制的视频送给h5端
* @param requestCode
* @param resultCode
* @param data
* @return
*/
public boolean receiveH5FaceVerifyResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VIDEO_REQUEST) { //根据请求码判断返回的是否是h5刷脸结果
if (null == mUploadMessage && null == mUploadCallbackAboveL) {
return true;
}
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
Uri[] uris = result == null ? null : new Uri[]{result};
if (mUploadCallbackAboveL != null) {
mUploadCallbackAboveL.onReceiveValue(uris);
setmUploadCallbackAboveL(null);
} else {
mUploadMessage.onReceiveValue(result);
setmUploadMessage(null);
}
return true;
}
return false;
}
/**
* 传统录制模式,针对5.0以下设备
*/
public boolean recordVideoForApiBelow21(ValueCallback<Uri> uploadMsg, String acceptType, Activity activity) {
if (isTencentH5FaceVerify(null,null,acceptType)) { //是腾讯的H5刷脸
setmUploadMessage(uploadMsg);
recordVideo(activity);
return true;
}
return false;
}
/**
* 传统录制模式,针对5.0以上设备
*/
@TargetApi(21)
public boolean recordVideoForApi21(WebView webView, ValueCallback<Uri[]> filePathCallback, Activity activity, WebChromeClient.FileChooserParams fileChooserParams) {
Log.d("test", "recordVideoForApi21 url=" + webView.getUrl());
if (isTencentH5FaceVerify(webView,fileChooserParams,null)){ //是腾讯的H5刷脸
setmUploadCallbackAboveL(filePathCallback);
recordVideo(activity);
return true;
}
return false;
}
/**
* 传统录制模式,调用系统前置摄像头进行视频录制
*/
private void recordVideo(Activity activity) {
try {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("android.intent.extras.CAMERA_FACING", 1); // 调用前置摄像头
activity.startActivityForResult(intent, VIDEO_REQUEST);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setmUploadMessage(ValueCallback<Uri> uploadMessage) {
mUploadMessage = uploadMessage;
}
public void setmUploadCallbackAboveL(ValueCallback<Uri[]> uploadCallbackAboveL) {
mUploadCallbackAboveL = uploadCallbackAboveL;
}
/**
* 判断是否腾讯的h5刷脸,根据acceptType参数值或者url判断
*/
public boolean isTencentH5FaceVerify(WebView webView, WebChromeClient.FileChooserParams fileChooserParams, String acceptType) {
if ("video/kyc".equals(acceptType)) {
return true;
} else if (fileChooserParams != null && fileChooserParams.getAcceptTypes() != null && fileChooserParams.getAcceptTypes().length > 0 && "video/kyc".equals(fileChooserParams.getAcceptTypes()[0])) {
return true;
}else if (webView!=null&& !TextUtils.isEmpty(webView.getUrl())){
String h5Url=webView.getUrl();
try{
String thirdName=h5Url.split("//")[1].split("\\.")[0];
Log.d("test","thirdUrlName "+thirdName);
if (thirdName.contains("kyc")||thirdName.contains("ida")){
return true;
}else {
return false;
}
}catch (Exception e){
e.printStackTrace();
return false;
}
}else {
return false;
}
}
/**
* 判断是否腾讯域名
* @param h5Url
* @return
*/
public boolean isTencentH5FaceVerify(String h5Url) {
try{
String thirdName=h5Url.split("//")[1].split("\\.")[0];
Log.d("test","isTencentH5FaceVerify thirdUrlName="+thirdName);
if (thirdName.contains("kyc")||thirdName.contains("ida")){
return true;
}else {
return false;
}
}catch (Exception e){
e.printStackTrace();
return false;
}
}
/**
* 录制模式中, 给ValueCallback接口的onReceiveValue抽象方法传入nul。尤其拒绝权限后,要记得调用这个方法,否则再次点击【开始录制】按钮会没有响应
* 回调onShowFileChooser这个方法,在这个重写的方法里面打开系统相机进行拍照或者录制,点击一次回调一次的前提是
* 请求被取消,而取消该请求回调的方法: 给ValueCallback接口的onReceiveValue抽象方法传入nul,同时onShowFileChooser方法返回true;
* 详情参考 https://www.teachcourse.cn/2224.html
*/
public void resetReceive(){
if (mUploadCallbackAboveL!=null){
mUploadCallbackAboveL.onReceiveValue(null);
}
if (mUploadMessage!=null){
mUploadMessage.onReceiveValue(null);
}
}
}
package com.clx.account_center
import android.content.Context
import android.os.Environment
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel
import java.io.*
import java.nio.channels.FileChannel
object FileUtil {
@Throws(IOException::class)
fun copyFile(sourceFile: File, destFile: File) {
if (destFile.parentFile?.exists() != true) {
destFile.parentFile?.mkdirs()
}
var sourceChannel: FileChannel? = null
var destChannel: FileChannel? = null
try {
sourceChannel = FileInputStream(sourceFile).channel
destChannel = FileOutputStream(destFile).channel
sourceChannel.transferTo(0, sourceChannel.size(), destChannel)
} finally {
sourceChannel?.close()
destChannel?.close()
}
}
@Throws(IOException::class)
fun copyFileToOutStream(sourceFile: File, destFile: OutputStream) {
try {
destFile.read(FileInputStream(sourceFile))
destFile.flush()
destFile.close()
} finally {
}
}
fun OutputStream.read(input: FileInputStream) {
use {
input.use {
var len: Int
val buffer = ByteArray(1024)
while (input.read(buffer).also { len = it } > 0) {
write(buffer, 0, len)
}
flush()
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".H5Activity">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="53dp" />
<ImageView
android:id="@+id/back"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="40dp"
android:layout_height="40dp"
android:padding="5dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="5dp"
android:src="@drawable/ic_cancel"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_title"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="45dp"/>
<WebView
android:id="@+id/webview"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/btn_finish"
android:layout_marginEnd="20.dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="35.dp"
android:src="@drawable/ic_cancel"
android:layout_height="35.dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<resources></resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Status bar color -->
<item name="android:statusBarColor">@android:color/white</item>
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M967.111111 967.111111V645.802667H378.197333V56.888889H56.888889v910.222222z" fill="#1F59EF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M56.888889 967.111111V645.802667h588.913778V56.888889H967.111111v910.222222z" fill="#1F59EF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M893.824 550.4V464c0-36.48-30.272-67.2-66.176-67.2H572.352V320h160.768c20.8 0 37.76-17.28 37.76-38.4V166.4c0-21.12-16.96-38.4-37.76-38.4h-378.24c-20.8 0-37.76 17.28-37.76 38.4v115.2c0 21.12 16.96 38.4 37.76 38.4h160.768v76.8H260.352c-35.904 0-66.176 30.72-66.176 67.2V550.4h-28.352c-20.8 0-37.824 17.28-37.824 38.4v268.8c0 21.12 17.024 38.4 37.76 38.4h113.536c20.8 0 37.76-17.28 37.76-38.4V588.8c0-21.12-16.96-38.4-37.76-38.4H250.88V464c0-5.76 3.84-9.6 9.472-9.6h255.296v96h-28.352c-20.8 0-37.824 17.28-37.824 38.4v268.8c0 21.12 17.024 38.4 37.76 38.4h113.472c20.8 0 37.824-17.28 37.824-38.4V588.8c0-21.12-17.024-38.4-37.76-38.4h-28.416V454.4h255.296c5.632 0 9.472 3.84 9.472 9.6V550.4h-28.416c-20.8 0-37.76 17.28-37.76 38.4v268.8c0 21.12 16.96 38.4 37.76 38.4h113.472c20.8 0 37.824-17.28 37.824-38.4V588.8c0-21.12-17.024-38.4-37.76-38.4h-28.416zM373.76 262.4V185.6h340.352v76.8H373.824z" fill="#1F59EF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M768.938667 93.866667H256.085333a42.666667 42.666667 0 0 0-30.549333 12.885333L41.514667 295.338667a128 128 0 0 0 1.024 179.84l441.472 442.026666a42.666667 42.666667 0 0 0 60.16 0.170667l83.584-82.56 356.309333-359.424a128 128 0 0 0 0.554667-179.712l-185.173334-189.013333a42.666667 42.666667 0 0 0-30.506666-12.8z" fill="#6B8CF9" /><path d="M611.968 549.333333l24.405333 106.24a9.898667 9.898667 0 0 1-3.498666 9.813334l-114.261334 92.202666a11.221333 11.221333 0 0 1-13.909333 0l-112.256-90.624 219.52-117.632z m-13.653333-59.093333l8.661333 37.546667L389.546667 644.266667l9.813333-42.922667 198.997333-111.104z m-44.373334-193.066667l39.424 171.434667-187.562666 104.746667 63.402666-276.053334c9.130667 1.024 18.389333 1.834667 27.904 2.261334l14.506667 0.298666c14.549333 0 28.714667-1.109333 42.325333-2.688zM463.189333 268.202667c15.36 2.474667 31.445333 4.181333 48.426667 4.181333s33.066667-1.706667 48.426667-4.181333l23.594666-40.277334c3.84-6.570667-1.28-14.592-9.386666-14.592h-125.312c-8.021333 0-13.098667 8.021333-9.344 14.592l23.594666 40.277334z" fill="#FFFFFF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M967.111111 56.888889v321.308444H378.197333V967.111111H56.888889v-910.222222z" fill="#1F59EF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="200px" height="200.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M56.888889 56.888889v321.308444h588.913778V967.111111H967.111111v-910.222222z" fill="#1F59EF" /></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1683870226148" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2701"
width="200" height="200"><path d="M590.208 571.328V551.04a19.968 19.968 0 0 0-19.52-20.288H492.416a19.968 19.968 0 0 0-19.52 20.288v20.288c0 11.136 8.768 20.288 19.52 20.288h11.776L473.6 709.696a8.448 8.448 0 0 0 1.408 6.528l47.104 65.28a11.584 11.584 0 0 0 9.408 4.928 11.584 11.584 0 0 0 9.344-4.864l47.168-65.344a8.448 8.448 0 0 0 1.344-6.528l-30.528-118.08h11.776a19.968 19.968 0 0 0 19.52-20.288z" fill="#1F59EF" p-id="2702"></path><path d="M770.944 551.04l-44.608-10.176a19.072 19.072 0 0 0-20.928 9.728L543.68 851.2a13.696 13.696 0 0 1-24.256 0L353.408 542.72a18.752 18.752 0 0 0-20.928-9.664l-79.36 18.048c-54.336 11.84-93.12 61.568-93.12 119.104v144.64c0 44.864 35.008 81.216 78.208 81.216h547.584c43.2 0 78.208-36.352 78.208-81.152V670.08c0-57.6-38.912-107.328-93.056-119.104zM531.584 64c96.768 0 176 82.176 176 182.656v81.152c0 100.48-79.232 182.656-176 182.656-96.832 0-176-82.24-176-182.656V246.656C355.584 146.176 434.752 64 531.584 64z m0 64c-60.928 0-112 52.992-112 118.656v81.152c0 65.6 51.072 118.656 112 118.656 60.864 0 112-53.056 112-118.656V246.656C643.584 180.992 592.448 128 531.584 128z" fill="#1F59EF" p-id="2703"></path></svg>
\ No newline at end of file
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
channel: "stable"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
- platform: web
create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
# account_center_example
Demonstrates how to use the account_center plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.clx.account_center_example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 21
targetSdkVersion 32
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
packagingOptions {
/// 阿里和pdf插件 so库冲突
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/armeabi-v7a/libc++_shared.so"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.clx.account_center_example">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.clx.account_center_example">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 必要权限,安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<!--拨打电话权限-->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--允许获取粗略位置,粗略定位必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:label="account_center_example"
android:name="${applicationName}"
android:icon="@drawable/img">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="com.clx.account_center.H5Activity"
android:exported="true">
<!-- 深度链接配置 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="clx"
android:host="msl-detection-app" /> <!-- 自己产品的productCode -->
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package com.clx.account_center_example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论