Commit 59067a29ad8f2e61fa02cc9253cd494e31e67d59

Authored by wdn127929
1 parent 9d9ba4a3

newnew

Showing 84 changed files with 103 additions and 3148 deletions
... ... @@ -83,8 +83,8 @@ android {
ndk {
//选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'arm64-v8a', 'x86_64', 'mips64' //魅族64位,不支持32位
// abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86_64','x86', 'mips', 'mips64'
// abiFilters 'arm64-v8a', 'x86_64', 'mips64' //魅族64位,不支持32位
abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86_64','x86', 'mips', 'mips64'
}
lintOptions {
... ...
... ... @@ -2834,6 +2834,84 @@ class NotebookDetailPageState extends State<NotebookDetailPage>
]);
}
_goCustomerDetail(isVVip) {
//管理员和店长跳转全店客情
// 其他人是自己的客户跳转,不是置灰
UserModel userModel = Provider.of<UserModel>(context, listen: false);
if (userModel.user!.role_name == '管理员' ||
userModel.user!.role_name == '店长') {
//gid 跳转客户详情页面
CustomerBySellerSunModel userHistoryEntity = CustomerBySellerSunModel(
null,
null,
detailModel!.detailModelAllSunModel!.phone,
null,
null,
null,
null,
null,
null,
null,
null,
detailModel!.detailModelAllSunModel!.gid,
null,
null,
null,
null);
if (isVVip) {
NavigatorUtil.goCustomerDetailPage(
context, userHistoryEntity, FromPage.FromPageMessagePage);
} else {
NavigatorUtil.goCustomerDetailPageSim(context, userHistoryEntity);
}
} else if (userModel.user!.openid ==
detailModel!.detailModelAllSunModel!.guestUid) {
//当前客户是登录人的客户
// 进入我的客户详情
CustomerListSunModel userHistoryEntity = CustomerListSunModel(
detailModel!.detailModelAllSunModel!.gid,
null,
null,
null,
null,
detailModel!.detailModelAllSunModel!.phone,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
);
if (isVVip) {
NavigatorUtil.goMyCustomerDetailPage(context, userHistoryEntity,
FromPage.FromPageMyCustomer, userModel.user!.openid);
} else {
NavigatorUtil.goMyCustomerDetailPageSim(
context,
userHistoryEntity,
);
}
} else {
Utils.showToast('您没有权限查看');
}
}
@override
Widget build(BuildContext context) {
if (MediaQuery.of(context).viewInsets.bottom == 0) {
... ... @@ -4486,95 +4564,20 @@ class NotebookDetailPageState extends State<NotebookDetailPage>
24,
onPressed:
() {
if (!detailModel!
.sellerPreserve) {
//没有购买客情维护模块
//提示购买
DialogUtil.showSellerVersionBuyDialog(
context,
'客情维护',
(v) {});
return;
}
//管理员和店长跳转全店客情
// 其他人是自己的客户跳转,不是置灰
UserModel
userModel =
Provider.of<UserModel>(context,
listen: false);
if (userModel.user!.role_name ==
'管理员' ||
userModel.user!.role_name ==
'店长') {
//gid 跳转客户详情页面
CustomerBySellerSunModel userHistoryEntity = CustomerBySellerSunModel(
null,
null,
detailModel!.detailModelAllSunModel!.phone,
null,
null,
null,
null,
null,
null,
null,
null,
detailModel!.detailModelAllSunModel!.gid,
null,
null,
null,
null);
NavigatorUtil.goCustomerDetailPage(
context,
userHistoryEntity,
FromPage.FromPageMessagePage);
} else if (userModel.user!.openid ==
detailModel!.detailModelAllSunModel!.guestUid) {
//当前客户是登录人的客户
// 进入我的客户详情
CustomerListSunModel
userHistoryEntity =
CustomerListSunModel(
detailModel!.detailModelAllSunModel!.gid,
null,
null,
null,
null,
detailModel!.detailModelAllSunModel!.phone,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
);
NavigatorUtil.goMyCustomerDetailPage(
context,
userHistoryEntity,
FromPage.FromPageMyCustomer,
userModel.user!.openid);
if (detailModel!
.sellerNormalSpecial) {
//标准版
if (detailModel!
.sellerPreserve) {
//进入超能版客情
_goCustomerDetail(true);
} else {
_goCustomerDetail(false);
}
} else {
Utils.showToast(
'您没有权限查看');
//进入超能版客情
_goCustomerDetail(
true);
}
},
),
... ...
... ... @@ -161,7 +161,7 @@ class NoteBookPageState extends State<NoteBookPage> {
}
getSellerVersion() async {
await collectStoreProvider.getSellerVersion(context);
await collectStoreProvider.getSellerVersion(context,showLoading: false);
}
/// 第一个显示今天
... ... @@ -299,7 +299,7 @@ class NoteBookPageState extends State<NoteBookPage> {
getDzSellerConfTemp() async {
MarketingCenterProvider marketingCenterProvider =
Provider.of<MarketingCenterProvider>(context, listen: false);
bool success = await marketingCenterProvider.getDzSellerConf(context);
bool success = await marketingCenterProvider.getDzSellerConf(context,showLoading: false);
if (success && marketingCenterProvider.dzSellerConfModel != null) {
cancelDay = marketingCenterProvider.dzSellerConfModel!.cancelDay;
cancelShopowner =
... ...
# 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
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/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: eb6d86ee27deecba4a83536aa20f366a6044895c
channel: stable
project_type: plugin
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
- platform: android
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
- platform: ios
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c
# 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.
# flutter_wxwork
A new Flutter plugin project.
## 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
85811fdeeab3e6378f1ae757e3e45719
\ No newline at end of file
e2d7230103f0366b3ab9986f409c06c6c37b398d
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/TR/xmlschema-1/">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tecent</groupId>
<artifactId>sdk</artifactId>
<version>2.0.12</version>
<packaging>aar</packaging>
</project>
4d692fdbce7e06bf09e5154e8c7339be
\ No newline at end of file
b104313c20c0682d7d488805d61db889a9cc7ea9
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>com.tecent</groupId>
<artifactId>sdk</artifactId>
<versioning>
<release>2.0.12</release>
<versions>
<version>2.0.12</version>
</versions>
<lastUpdated>20230706035721</lastUpdated>
</versioning>
</metadata>
0845877a0e8540a7882cdc2fc4dbbc07
\ No newline at end of file
9d8eb88e3c52335f161001635c9a87d88388e444
\ No newline at end of file
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
// 拷贝aar的方法
static aarFileCopy(String srcPath,String desPath) {
System.out.println("copy aar from <<${srcPath}>> to <<${desPath}>>")
try {
FileInputStream fis = new FileInputStream(srcPath)
FileOutputStream fos = new FileOutputStream(desPath)
byte[] data = new byte[1024*8]
int len = 0
while ((len = fis.read(data))!=-1) {
fos.write(data,0,len)
}
fis.close()
fos.close()
}catch(Exception e) {
e.printStackTrace()
}
}
//把aar拷贝进入主项目的方法 com.example.android_control换成你自己的插件名
copyAar2Host('com.wxwork.flutter_wxwork')
void copyAar2Host(String pluginGroup) {
Project currentProject = null
Project appProject = null
rootProject.allprojects.each {
p->
boolean isApp = p.plugins.hasPlugin("com.android.application")
println("<<${p.name}>> isHost ? ${isApp}")
if (p.group == pluginGroup) {
currentProject = p
println("Plugin project name is $currentProject")
}
if(isApp) {
appProject = p
println("Host project name is <<${p.name}>>")
}
}
Set<File> aarFiles = new HashSet<File>()
if (appProject != null && currentProject != null) {
File libs = new File("${currentProject.projectDir}","libs")
if(libs.isDirectory()) {
libs.listFiles().each {
f->
if(f.name.endsWith(".aar")) {
println("The aar file name to be copied is <<${f.name}>>")
aarFiles.add(f)
}
}
}
if (!aarFiles.isEmpty()) {
File applibs = new File("${appProject.projectDir}${File.separator}libs")
if(!applibs.isDirectory()) {
applibs.mkdirs()
}
aarFiles.each {
f->
File copyAar = new File("${appProject.projectDir}${File.separator}libs",f.name)
if(!copyAar.exists()) {
copyAar.createNewFile()
aarFileCopy(f.path,copyAar.path)
} else {
}
}
appProject.dependencies {
implementation fileTree(dir:"${appProject.projectDir}${File.separator}libs",include:["*.jar","*.aar"])
}
}
}
}
repositories{
flatDir {
dirs 'libs'
}
}
group 'com.wxwork.flutter_wxwork'
version '1.0'
buildscript {
repositories {
// maven {
// url 'file:/Users/wangdongni/Desktop/oneKey_wdn_none_safty/Flutter-ReserveApp/library/flutter_wxwork/android/libs/maven/'
// }
// //先查找本地仓库
// mavenLocal()
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.1'
}
}
allprojects {
repositories {
// maven {
// url 'file:/Users/wangdongni/Desktop/oneKey_wdn_none_safty/Flutter-ReserveApp/library/flutter_wxwork/android/libs/maven'
// }
// //先查找本地仓库
// mavenLocal()
google()
mavenCentral()
// google()
// jcenter()
}
}
apply plugin: 'com.android.library'
apply from: './aar_tools.gradle'
android {
compileSdkVersion 33
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
}
dependencies {
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.0.0'
// implementation fileTree (dir:"../libs/maven/com/example/mylibrary/1.0",include:["*.jar","*.aar"])
// implementation 'com.example:mylibrary:1.0'
// implementation files('../libs/maven/com/example/mylibrary/1.0/mylibrary-1.0.aar')
// implementation (fileTree("lib"))
// implementation fileTree(dir: 'lib', include: ['*.aar'])
// implementation (files ("lib/lib_wwapi-2.0.12.11.aar"))
// implementation project(path: ':lib:wxwork')
// implementation (fileTree("libs"))
// api fileTree(dir: "libs", include: ["*.jar", "*.aar"])
// compileOnly fileTree(includes: [".aar"],dir:"libs")
// compileOnly fileTree(includes: ["*.aar"],dir:"libs")
// compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
// compileOnly("androidx.annotation:annotation:1.0.0")
}
testOptions {
unitTests.all {
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen { false }
showStandardStreams = true
}
}
}
}
//读取配置
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') {
reader-> localProperties.load(reader)
}
}
//获取flutter sdk路径
def flutterRoot = localProperties.getProperty('flutter.sdk')
if(flutterRoot == null) {
throw new GradleException('Flutter sdk not found.')
}
dependencies {
compileOnly fileTree(includes: ["*.aar"],dir:"libs")
compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
compileOnly("androidx.annotation:annotation:1.0.0")
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.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 \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# 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% equ 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% equ 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!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
sdk.dir=/Users/wangdongni/Library/Android/sdk
flutter.sdk=/Users/wangdongni/Documents/flutter
# aar.mylibrary.path=/libs/lib_wwapi-2.0.12.11.aar
\ No newline at end of file
rootProject.name = 'flutter_wxwork'
include ':lib:wxwork'//新增,写上你新写的module
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wxwork.flutter_wxwork">
</manifest>
package com.wxwork.flutter_wxwork;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private OnBitmapDownloadListener listener;
public DownloadImageTask(OnBitmapDownloadListener listener) {
this.listener = listener;
}
@Override
protected Bitmap doInBackground(String... urls) {
String urlString = urls[0];
Bitmap bitmap = null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream inputStream = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
listener.onBitmapDownloaded(bitmap);
}
public interface OnBitmapDownloadListener {
void onBitmapDownloaded(Bitmap bitmap);
}
}
\ No newline at end of file
package com.wxwork.flutter_wxwork;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
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.tencent.wework.api.model.WWMediaText;
// package com.example.flutter_wxwork;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import com.tencent.wework.api.IWWAPI;
import com.tencent.wework.api.IWWAPIEventHandler;
import com.tencent.wework.api.WWAPIFactory;
import com.tencent.wework.api.model.BaseMessage;
import com.tencent.wework.api.model.WWAuthMessage;
import com.tencent.wework.api.model.WWMediaMiniProgram;
import com.tencent.wework.api.model.WWSimpleRespMessage;
import java.net.HttpURLConnection;
import java.net.URL;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.wxwork.flutter_wxwork.LoadImageUtil;
import com.wxwork.flutter_wxwork.NetWorkUtils;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import android.view.View;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
/**
* FlutterWxworkPlugin
*/
public class FlutterWxworkPlugin implements FlutterPlugin, MethodCallHandler {
/// 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 String APPID;
private String AGENTID;
private String SCHEMA;
private IWWAPI iwwapi;
private Context context;
private static final int SHARE_MINI_PROGRAM_THUMB_LENGTH = 120 ;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "flutter_wxwork");
channel.setMethodCallHandler(this);
context = flutterPluginBinding.getApplicationContext();
iwwapi = WWAPIFactory.createWWAPI(context);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
@SuppressWarnings("unchecked")
Map<String, String> arguments = (Map<String, String>) call.arguments;
if (call.method.equals("isAppInstalled")) {
boolean installed = iwwapi.isWWAppInstalled();
// if (installed) {
result.success(installed);
// } else {
// result.success("0");
// }
} else if (call.method.equals("register")) {
APPID = arguments.get("corpId");
SCHEMA = arguments.get("scheme");
AGENTID = arguments.get("agentId");
boolean hasRegister = iwwapi.registerApp(SCHEMA);
// if (hasRegister) {
result.success(hasRegister);
// } else {
// result.success("0");
// }
} else if (call.method.equals("auth")) {
String state = arguments.get("state");
final WWAuthMessage.Req req = new WWAuthMessage.Req();
req.sch = SCHEMA;
req.appId = APPID;
req.agentId = AGENTID;
req.state = state;
// Toast.makeText(context, "sch:" + req.sch,
// Toast.LENGTH_SHORT).show();
iwwapi.sendMessage(req, new IWWAPIEventHandler() {
@Override
public void handleResp(BaseMessage resp) {
if (resp instanceof WWAuthMessage.Resp) {
WWAuthMessage.Resp rsp = (WWAuthMessage.Resp) resp;
Map<String, String> map = new HashMap<>();
map.put("code", rsp.code);
map.put("errCode", String.valueOf(rsp.errCode));
map.put("state", String.valueOf(rsp.state));
result.success(map);
}
}
});
}else if (call.method.equals("shareImageNetWork")) {
// APPID = arguments.get("corpId");
// SCHEMA = arguments.get("scheme");
// AGENTID = arguments.get("agentId");
// boolean hasRegister = iwwapi.registerApp(SCHEMA);
// // if (hasRegister) {
// result.success(hasRegister);
// // } else {
// // result.success("0");
// // }
} else if (call.method.equals("shareImagePath")) {
}else if (call.method.equals("shareMiniProgram")) {
WWMediaMiniProgram miniProgram = new WWMediaMiniProgram();
miniProgram.appPkg = "com.naji.one_key";
miniProgram.appName = "周到安排商家";//app name of this android pkg
miniProgram.appId = APPID; //企业唯一标识。创建企业后显示在,我的企业 CorpID字段
miniProgram.agentId = AGENTID; //应用唯一标识。显示在具体应用下的 AgentId字段
miniProgram.schema = SCHEMA;
miniProgram.username = arguments.get("userName"); //必须是应用关联的小程序,注意要有@app后缀
miniProgram.description = arguments.get("description");
miniProgram.path = arguments.get("path");
//得到图片
DownloadImageTask task = new DownloadImageTask(new DownloadImageTask.OnBitmapDownloadListener() {
@Override
public void onBitmapDownloaded(Bitmap bitmap) {
//缩略图建议不超过32kb
Bitmap thumbBmp = Bitmap.createScaledBitmap(bitmap, 500, 400, true);
bitmap.recycle();
miniProgram.hdImageData = bmpToByteArray(thumbBmp, true);
// 在这里处理下载到的Bitmap对象
// miniProgram.hdImageData = getBytesFromBitmap(bitmap);
miniProgram.title = arguments.get("title");
// 数据加载完毕后隐藏加载动画
result.success(true);
iwwapi.sendMessage(miniProgram, new IWWAPIEventHandler() {
@Override
public void handleResp(BaseMessage resp) {
if(resp instanceof WWSimpleRespMessage){
WWSimpleRespMessage rsp = (WWSimpleRespMessage)resp;
// String t = "";
// Toast.makeText(MainActivity.this,
// t = "发小程序," + rsp.errCode + "," + rsp.errMsg,
// Toast.LENGTH_LONG).show();
Map<String, String> map = new HashMap<>();
map.put("code", String.valueOf(rsp.errCode));
map.put("errCode", String.valueOf(rsp.errMsg));
// result.success(map);
}else{
// result.success(true);
}
}
});
}
});
Log.i("ExampleClass", "Value: " + arguments.get("hdImageData"));
task.execute(arguments.get("hdImageData"));
// LoadImageUtil loadImageUtil = new LoadImageUtil(context);
// Bitmap bitmap = loadImageUtil.loadBitmapByImgUrl(arguments.get("hdImageData"), new LoadImageUtil.CallBack() {
// @Override
// public void callBack(String imgUrl, Bitmap bitmap) {
// if(bitmap != null){
//// ImageView img = (ImageView) parent.findViewWithTag(imgUrl);
//// img.setImageBitmap(bitmap);
// miniProgram.hdImageData = getBytesFromBitmap(bitmap);
// miniProgram.title = arguments.get("title");
// iwwapi.sendMessage(miniProgram, new IWWAPIEventHandler() {
// @Override
// public void handleResp(BaseMessage resp) {
// if(resp instanceof WWSimpleRespMessage){
// WWSimpleRespMessage rsp = (WWSimpleRespMessage)resp;
//// String t = "";
//// Toast.makeText(MainActivity.this,
//// t = "发小程序," + rsp.errCode + "," + rsp.errMsg,
//// Toast.LENGTH_LONG).show();
//
// Map<String, String> map = new HashMap<>();
// map.put("code", String.valueOf(rsp.errCode));
// map.put("errCode", String.valueOf(rsp.errMsg));
//
//
// result.success(map);
// }
// }
// });
// }
//
// }
// });
// if(bitmap != null){//如果图片在缓存中,直接获取展示
// miniProgram.hdImageData = getBytesFromBitmap(bitmap);
// miniProgram.title = arguments.get("title");
// iwwapi.sendMessage(miniProgram, new IWWAPIEventHandler() {
// @Override
// public void handleResp(BaseMessage resp) {
// if(resp instanceof WWSimpleRespMessage){
// WWSimpleRespMessage rsp = (WWSimpleRespMessage)resp;
//// String t = "";
//// Toast.makeText(MainActivity.this,
//// t = "发小程序," + rsp.errCode + "," + rsp.errMsg,
//// Toast.LENGTH_LONG).show();
//
// Map<String, String> map = new HashMap<>();
// map.put("code", String.valueOf(rsp.errCode));
// map.put("errCode", String.valueOf(rsp.errMsg));
//
//
// result.success(map);
// }
// }
// });
// }
// Bitmap bitmap = getBitmapFromURL(arguments.get("hdImageData"));
// ByteArrayOutputStream stream = new ByteArrayOutputStream();
// bitmap.compress(Bitmap.CompressFormat.JPEG, 0, stream);
// byte[] byteArray = stream.toByteArray();
//
}else if (call.method.equals("shareText")) {
WWMediaText txt = new WWMediaText( arguments.get("text")
);
txt.appPkg = "com.naji.one_key";
txt.appName = "周到安排商家" ;
txt.appId = APPID; //企业唯一标识。创建企业后显示在,我的企业 CorpID字段
txt.agentId = AGENTID; //应用唯一标识。显示在具体应用下的 AgentId字段
iwwapi.sendMessage(txt);
}
else {
// result(FlutterMethodNotImplemented);
}
}
// 转换图片格式为字节数组
public static byte[] bmpToByteArray(final Bitmap bmp, final boolean needRecycle) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, output);
if (needRecycle) {
bmp.recycle();
}
byte[] result = output.toByteArray();
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static Bitmap compressBitmap(String imgPath, int targetWidth, int targetHeight, int quality, Bitmap.CompressFormat compressFormat) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imgPath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float ratio = actualWidth / (float) actualHeight;
options.inSampleSize = 1;
while ((actualWidth / 2) > targetWidth && (actualHeight / 2) > targetHeight) {
actualWidth /= 2;
actualHeight /= 2;
options.inSampleSize *= 2;
}
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, targetWidth, (int) (targetWidth / ratio), true);
bitmap.recycle();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
scaledBitmap.compress(compressFormat, quality, byteArrayOutputStream);
scaledBitmap.recycle();
return BitmapFactory.decodeByteArray(byteArrayOutputStream.toByteArray(), 0, byteArrayOutputStream.size());
}
public static byte[] getBytesFromBitmap(Bitmap bitmap) {
// Bitmap compressedImage = compressBitmap(bitmap,100);
ByteBuffer byteBuffer = ByteBuffer.allocate(bitmap.getByteCount());
bitmap.copyPixelsToBuffer(byteBuffer);
return byteBuffer.array();
}
/**
* 压缩图片
*
* @param bitmap
* 被压缩的图片
* @param sizeLimit
* 大小限制
* @return
* 压缩后的图片
*/
private static Bitmap compressBitmap(Bitmap bitmap, long sizeLimit) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int quality = 10;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
// 循环判断压缩后图片是否超过限制大小
while(baos.toByteArray().length / 1024 > sizeLimit) {
// 清空baos
baos.reset();
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
quality -= 10;
}
Bitmap newBitmap = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), null, null);
return newBitmap;
}
// public static Bitmap compressBitmapToSize(Bitmap bitmap, int maxSizeKB) {
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// bitmap.compress(getBitmapCompressFormat(bitmap), 100, baos); // 假设压缩格式为JPEG
// int options = 100;
//
// int bytes = baos.toByteArray().length/1024;
////
// // 如果Bitmap的大小已经小于或等于指定的大小,则不需要进一步压缩
// while (bytes > maxSizeKB ) {
// // 每次减少质量,然后重新压缩
// options -= 5; // 降低质量
// baos.reset(); // 重置baos来清除数据
// bitmap.compress(getBitmapCompressFormat(bitmap), options, baos);
//
//
// bytes = baos.toByteArray().length/1024;
// }
//
//
//
//// while (baos.toByteArray().length / 1024 > maxSizeKB && options != 10) {
//// baos.reset(); // 清空baos以复用
//// options -= 10; // 每次减少10
//// bitmap.compress(getBitmapCompressFormat(bitmap), options, baos);
//// }
// ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
// Bitmap compressedBitmap = BitmapFactory.decodeStream(isBm, null, null);
// // 释放资源
// baos.reset();
// try {
// baos.close();
// isBm.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return compressedBitmap;
// }
// public static Bitmap compressImage(Bitmap bitmap){
// int height = (int) ( bitmap.getHeight() * (512.0 / bitmap.getWidth()) );
// bitmap = Bitmap.createScaledBitmap(bitmap, 512, height, true);
// return bitmap;
// }
// public static Bitmap compressBitmapToSize(Bitmap image, int maxSizeKB) {
// ByteArrayOutputStream stream = new ByteArrayOutputStream();
// // 计算压缩比例
// int quality = 100;
// image.compress(Bitmap.CompressFormat.JPEG, quality, stream);
// // 如果图片大小大于指定大小,则以压缩质量为基准重复压缩
// while ((stream.toByteArray().length / 1024) > maxSizeKB && quality > 0) {
// stream.reset(); // 重置流以复用
// quality -= 5; // 每次减少5%的质量
// image.compress(getBitmapCompressFormat(image), quality, stream);
// }
// // 将流转换为字节
// byte[] imageBytes = stream.toByteArray();
// // 将字节转换为Bitmap
// Bitmap compressedImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
// // 释放资源
//
//// 关闭流
// try {
// stream.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return compressedImage;
// }
// public static Bitmap compressBitmapToSize(Bitmap bitmap, int maxSizeKB) {
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// int quality = 100;
// int bytes = baos.toByteArray().length;
//
// // 如果Bitmap的大小已经小于或等于指定的大小,则不需要进一步压缩
// while (bytes > maxSizeKB ) {
// // 每次减少质量,然后重新压缩
// quality -= 5; // 降低质量
// baos.reset(); // 重置baos来清除数据
// bitmap.compress(getBitmapCompressFormat(bitmap), quality, baos);
//
//
// bytes = baos.toByteArray().length;
// }
//
// // 将压缩后的数据转换回Bitmap对象
// ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
// Bitmap compressedBitmap = BitmapFactory.decodeStream(isBm, null, null);
// // 关闭流
// try {
// baos.close();
// isBm.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return compressedBitmap;
// }
public static Bitmap.CompressFormat getBitmapCompressFormat(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
return Bitmap.CompressFormat.PNG;
}
switch (config) {
case RGB_565:
return Bitmap.CompressFormat.JPEG;
case ALPHA_8:
case ARGB_4444:
case ARGB_8888:
return Bitmap.CompressFormat.PNG;
default:
return Bitmap.CompressFormat.WEBP;
}
}
// public static Bitmap getBitmapFromURL(String imageUrl) {
// HttpURLConnection connection = null;
// try {
// URL url = new URL(imageUrl);
// connection = (HttpURLConnection) url.openConnection();
// connection.setDoInput(true);
// connection.connect();
// BufferedInputStream inputStream = new BufferedInputStream(connection.getInputStream());
// Bitmap myBitmap = BitmapFactory.decodeStream(inputStream);
// inputStream.close();
// return myBitmap;
// } catch (IOException e) {
// e.printStackTrace();
// return null;
// } finally {
// if (connection != null) {
// connection.disconnect();
// }
// }
// }
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
\ No newline at end of file
package com.wxwork.flutter_wxwork;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import java.lang.ref.SoftReference;
import java.util.HashMap;
/**
* Created by Administrator on 2017/9/5.
*/
public class LoadImageUtil {
private Context context;
private HashMap<String,SoftReference<Bitmap>> bitMaps;
public LoadImageUtil(Context context) {
this.context = context;
this.bitMaps = new HashMap<String,SoftReference<Bitmap>>();//实例化缓存容器
}
//回调的接口
public interface CallBack{
public void callBack(String imgUrl,Bitmap bitmap);
}
//加载图片,进行缓存
public Bitmap loadBitmapByImgUrl(final String imgUrl, final CallBack callBack){
// //先判断缓存中有没有图片,得到图片
// SoftReference<Bitmap> soft = bitMaps.get(imgUrl);
// if(soft != null){
// Bitmap bitmap = soft.get();//从软引用中获得bitmap
// if(bitmap != null){//缓存中有次图片,直接用
// return bitmap;
// }else{
// bitMaps.remove(imgUrl);//key(图片的url)对应的bitmap消耗了,key也没有意义
// }
// }
//代码走到此处,说明缓存中没有图片,需要到第三级缓存:网络缓存去取
//通过handler实现子线程和ui主线程的通信
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bitmap bitmap = (Bitmap) msg.obj;
callBack.callBack(imgUrl,bitmap);
}
};
//启动线程访问图片
new Thread(){
@Override
public void run() {
super.run();
//加载图片
Bitmap bitmap = new NetWorkUtils().getBitmapByHttpUrlConnectionGet(imgUrl);
//压缩图片
//把bitmap缓存到缓存中,通过软引用
bitMaps.put(imgUrl,new SoftReference<Bitmap>(bitmap));
handler.sendMessage(handler.obtainMessage(1,bitmap));//发给handler
}
}.start();
// //内存中没有图片,通过次线程去加载,然后放在缓存中
// bitMaps.put(imgUrl,bitmap);
return null;
}
}
\ No newline at end of file
package com.wxwork.flutter_wxwork;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* 网络请求的工具类
* Created by Administrator on 2017/9/1.
*/
public class NetWorkUtils {
//获得json串的方法,通过HttpClient get
public String getJsonByHttpClientGet(String url){
return "";
}
//获得json串的方法,通过HttpClient get
public String getJsonByHttpUrlConnectionGet(String jsonUrl){
URL url = null;
HttpURLConnection httpURLConnection = null;
String strJson = "";
InputStream inputStream = null;
try {
url = new URL(jsonUrl);
httpURLConnection = (HttpURLConnection) url.openConnection();
int responseCode = httpURLConnection.getResponseCode();
if(responseCode == 200){
inputStream = httpURLConnection.getInputStream();
byte[] b = new byte[1024];
int length = 0;
while((length = inputStream.read(b)) != -1){//循环读取json串,拼装
strJson += new String(b,0,length);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return strJson;//返回最终的json数据
}
//获得json串的方法,通过HttpClient get
public Bitmap getBitmapByHttpUrlConnectionGet(String imageUrl){
URL url = null;
HttpURLConnection httpURLConnection = null;
Bitmap bitmap = null;
InputStream inputStream = null;
try {
url = new URL(imageUrl);
httpURLConnection = (HttpURLConnection) url.openConnection();
int responseCode = httpURLConnection.getResponseCode();
if(responseCode == 200){
inputStream = httpURLConnection.getInputStream();
bitmap = BitmapFactory.decodeStream(inputStream);//把图片信息(输入流)
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bitmap;//返回最终的json数据
}
}
\ No newline at end of file
.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
\ No newline at end of file
#import <Flutter/Flutter.h>
#import "WWKApi.h"
@interface FlutterWxworkPlugin : NSObject<FlutterPlugin,WWKApiDelegate>
@end
#import "FlutterWxworkPlugin.h"
#import "WWKApiObject.h"
@implementation FlutterWxworkPlugin
FlutterResult authResult;
FlutterMethodChannel *channel;
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
channel = [FlutterMethodChannel
methodChannelWithName:@"flutter_wxwork"
binaryMessenger:[registrar messenger]];
FlutterWxworkPlugin* instance = [[FlutterWxworkPlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if([@"isAppInstalled" isEqualToString:call.method]){
result(@([WWKApi isAppInstalled]));
}else if ([@"register" isEqualToString:call.method]) {
NSDictionary *dic = call.arguments;
NSString *scheme = dic[@"scheme"];
NSString *corpId = dic[@"corpId"];
NSString *agentId = dic[@"agentId"];
result(@([WWKApi registerApp:scheme corpId:corpId agentId:agentId]));
} else if ([@"auth" isEqualToString:call.method]){
WWKSSOReq *req = [[WWKSSOReq alloc] init];
// state参数为这次请求的唯一标示,客户端需要维护其唯一性。SSO回调时会原样返回
req.state = call.arguments[@"state"];
[WWKApi sendReq:req];
authResult = result;
}
else if ([@"shareImageNetWork" isEqualToString:call.method]) {
[self shareImageNetWork:call result:result];
}
else if([@"shareImagePath" isEqualToString:call.method]) {
[self shareImagePath:call result:result];
}
else if ([@"shareMiniProgram" isEqualToString:call.method]) {
[self shareMiniProgram:call result:result];
}else if ([@"shareText" isEqualToString:call.method]) {
[self shareText:call result:result];
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)shareText:(FlutterMethodCall *)call result:(FlutterResult)result {
WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
WWKMessageTextAttachment *attachment = [[WWKMessageTextAttachment alloc] init];
attachment.text = @"分享的文本内容";
req.attachment = attachment;
[WWKApi sendReq:req];
}
- (void)shareImageNetWork:(FlutterMethodCall *)call result:(FlutterResult)result {
// [WWKApi registerApp:@"wwauthbdca186ec4257973000006" corpId:@"wwbdca186ec4257973" agentId:@"1000006"];
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
dispatch_async(globalQueue, ^{
// 使用NSURLSession异步请求网络图片
NSURL *imageURL = [NSURL URLWithString:call.arguments[@"path"]];
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
// 创建URLSession并开始任务
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
// 处理错误
NSLog(@"Error: %@", error);
} else {
// 成功获取数据,转换为NSData
NSData *imageData = data;
dispatch_async(dispatch_get_main_queue(), ^{
WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
WWKMessageImageAttachment *attachment = [[WWKMessageImageAttachment alloc] init];
// attachment.filename = @"icon.jpg";
// attachment.path = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"jpg"];
// NSURL *imageURL = [NSURL URLWithString:@"http://nosqn.colorcun.com/reserve/images/3x/%E6%9A%82%E6%97%A0.png"];
// //下载图片
// NSData *data= [NSData dataWithContentsOfURL:imageURL];
attachment.filename = @"share_image";
attachment.data = imageData;
req.attachment = attachment;
[WWKApi sendReq:req];
authResult = result;
});
// 此处可以使用imageData,例如保存到本地或者用于其他处理
// 保存到本地示例代码
// [imageData writeToFile:@"/path/to/save/image.png" atomically:YES];
// 或者直接使用
// UIImage *image = [UIImage imageWithData:imageData];
}
}];
// 启动任务
[task resume];
});
// WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
// WWKMessageImageAttachment *attachment = [[WWKMessageImageAttachment alloc] init];
// attachment.filename = @"icon.jpg";
// attachment.path = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"jpg"];
// // NSURL *imageURL = [NSURL URLWithString:@"http://nosqn.colorcun.com/reserve/images/3x/%E6%9A%82%E6%97%A0.png"];
// // //下载图片
// // NSData *data= [NSData dataWithContentsOfURL:imageURL];
// // attachment.data = data;
// req.attachment = attachment;
// [WWKApi sendReq:req];
}
- (void)shareImagePath:(FlutterMethodCall *)call result:(FlutterResult)result {
// [WWKApi registerApp:@"wwauthbdca186ec4257973000006" corpId:@"wwbdca186ec4257973" agentId:@"1000006"];
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
dispatch_async(globalQueue, ^{
NSData *imageData= [NSData dataWithContentsOfFile:call.arguments[@"path"]];
dispatch_async(dispatch_get_main_queue(), ^{
WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
WWKMessageImageAttachment *attachment = [[WWKMessageImageAttachment alloc] init];
// attachment.filename = @"icon.jpg";
// attachment.path = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"jpg"];
// NSURL *imageURL = [NSURL URLWithString:@"http://nosqn.colorcun.com/reserve/images/3x/%E6%9A%82%E6%97%A0.png"];
// //下载图片
// NSData *data= [NSData dataWithContentsOfURL:imageURL];
attachment.filename = @"share_image";
attachment.data = imageData;
req.attachment = attachment;
[WWKApi sendReq:req];
authResult = result;
});
});
// WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
// WWKMessageImageAttachment *attachment = [[WWKMessageImageAttachment alloc] init];
// attachment.filename = @"icon.jpg";
// attachment.path = [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"jpg"];
// // NSURL *imageURL = [NSURL URLWithString:@"http://nosqn.colorcun.com/reserve/images/3x/%E6%9A%82%E6%97%A0.png"];
// // //下载图片
// // NSData *data= [NSData dataWithContentsOfURL:imageURL];
// // attachment.data = data;
// req.attachment = attachment;
// [WWKApi sendReq:req];
}
- (void)shareMiniProgram:(FlutterMethodCall *)call result:(FlutterResult)result {
// WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
// WWKMessageMiniAppAttachment *attachment = [[WWKMessageMiniAppAttachment alloc] init];
// attachment.userName = @"gh_487873d353b3@app"; //必须是应用关联的小程序,注意要有@app后缀
// attachment.path = @"pages/customer/index.html?id=563971&hasInvitation=1&hasSellerShare=1&uid=7035";
// // attachment.hdImageData = UIImageJPEGRepresentation([UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"bg_error" ofType:@"png"]], 1.0f);
// NSString *hdImageData = call.arguments[@"hdImageData"];
// NSURL *imageURL = [NSURL URLWithString:hdImageData];
// //下载图片
// NSData *data= [NSData dataWithContentsOfURL:imageURL];
// attachment.hdImageData = data;
// // attachment.hdImageData = UIImageJPEGRepresentation([UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"jpg"]], 1.0f);
// attachment.title = @"您预订的长安大排档总店(测试),已经安排,点击查看详情";
// req.attachment = attachment;
// [WWKApi sendReq:req];
// authResult = result;
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
dispatch_async(globalQueue, ^{
// 使用NSURLSession异步请求网络图片
NSURL *imageURL = [NSURL URLWithString:call.arguments[@"hdImageData"]];
NSURLRequest *request = [NSURLRequest requestWithURL:imageURL];
// 创建URLSession并开始任务
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
// 处理错误
NSLog(@"Error: %@", error);
} else {
// 成功获取数据,转换为NSData
NSData *imageData = data;
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableDictionary *mDic = [[NSMutableDictionary alloc]init];
result(mDic);
WWKSendMessageReq *req = [[WWKSendMessageReq alloc] init];
WWKMessageMiniAppAttachment *attachment = [[WWKMessageMiniAppAttachment alloc] init];
attachment.userName = call.arguments[@"userName"]; //必须是应用关联的小程序,注意要有@app后缀
attachment.path = call.arguments[@"path"];
attachment.hdImageData =imageData;
attachment.title = call.arguments[@"title"];
req.attachment = attachment;
[WWKApi sendReq:req];
authResult = result;
});
}}];
// 启动任务
[task resume];
});
}
// - (void)handleShare:(FlutterMethodCall *)call result:(FlutterResult)result {
// if ([@"shareText" isEqualToString:call.method]) {
// [self shareText:call result:result];
// } else if ([@"shareImage" isEqualToString:call.method]) {
// [self shareImage:call result:result];
// } else if ([@"shareWebPage" isEqualToString:call.method]) {
// [self shareWebPage:call result:result];
// } else if ([@"shareMusic" isEqualToString:call.method]) {
// [self shareMusic:call result:result];
// } else if ([@"shareVideo" isEqualToString:call.method]) {
// [self shareVideo:call result:result];
// } else if ([@"shareMiniProgram" isEqualToString:call.method]) {
// [self shareMiniProgram:call result:result];
// } else if ([@"shareFile" isEqualToString:call.method]) {
// [self shareFile:call result:result];
// }
// }
- (void)checkWWorkInstallation:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *str = [NSString stringWithFormat:@"%hhd",[WWKApi isAppInstalled]];
result(str);
// result(@([WWKApi isAppInstalled]));
}
- (void)registerApp:(FlutterMethodCall *)call result:(FlutterResult)result {
// NSNumber* doOnIOS =call.arguments[@"iOS"];
// if (![doOnIOS boolValue]) {
// result(@NO);
// return;
// }
// NSString *appId = call.arguments[@"appId"];
// if ([FluwxStringUtil isBlank:appId]) {
// result([FlutterError errorWithCode:@"invalid app id" message:@"are you sure your app id is correct ? " details:appId]);
// return;
// }
// NSString *universalLink = call.arguments[@"universalLink"];
// if ([FluwxStringUtil isBlank:universalLink]) {
// result([FlutterError errorWithCode:@"invalid universal link" message:@"are you sure your universal link is correct ? " details:universalLink]);
// return;
// }
NSString *scheme = call.arguments[@"scheme"]; // 第三方App的Schema
NSString *corpId = call.arguments[@"corpId"]; // 第三方App所属企业的ID
NSString *agentId = call.arguments[@"agentId"]; // 第三方App在企业内部的ID
// BOOL isWeChatRegistered = [WXApi registerApp:appId universalLink:universalLink];
BOOL isWWKRegistered = [WWKApi registerApp:scheme corpId:corpId agentId:agentId];
result(@(isWWKRegistered));
// result(@(isWeChatRegistered));
}
#pragma mark - AppDelegate
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options{
return [WWKApi handleOpenURL:url delegate:self];
}
- (BOOL)isBlankString:(NSString *)string{
if (string == nil) {
return YES;
}
if (string == NULL) {
return YES;
}
if ([string isKindOfClass:[NSNull class]]) {
return YES;
}
if ([[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0) {
return YES;
}
return NO;
}
- (void)onResp:(WWKBaseResp *)resp {
/*! @brief 所有通过sendReq发送的SDK请求的结果都在这个函数内部进行异步回调
* @param resp SDK处理请求后的返回结果 需要判断具体是哪项业务的回调
*/
/* SSO的回调 */
if ([resp isKindOfClass:[WWKSSOResp class]]) {
WWKSSOResp *r = (WWKSSOResp *)resp;
NSMutableDictionary *mDic = [[NSMutableDictionary alloc]init];
if([self isBlankString:r.code]){
[mDic setObject:@"1" forKey:@"errCode"];
[mDic setObject:@"" forKey:@"code"];
}else{
[mDic setObject:@"0" forKey:@"errCode"];
[mDic setObject:r.code forKey:@"code"];
}
[mDic setObject:r.state forKey:@"state"];
authResult(mDic);
// [channel invokeMethod:@"auth" arguments:mDic];
}else if([resp isKindOfClass:[WWKSendMessageResp class]]){
// NSMutableDictionary *mDic = [[NSMutableDictionary alloc]init];
// [mDic setObject:[NSString stringWithFormat:@"%@",resp.errStr]] forKey:@"errStr"];
// [mDic setObject:[NSString stringWithFormat:@"%d",resp.errCode]] forKey:@"errCode"];
// authResult(mDic);
}
}
@end
//
// WWKApi.h
// wxwork
//
// Created by WXWork on 16/5/25.
// Copyright © 2019年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "WWKApiObject.h"
#pragma mark - WWKApiDelegate
/*! @brief 接收并处理来自企业微信终端程序的事件消息
*
* 接收并处理来自企业微信终端程序的事件消息,期间企业微信界面会切换到第三方应用程序。
* WWKApiDelegate 会在handleOpenURL:delegate:中使用并触发。
*/
@protocol WWKApiDelegate <NSObject>
@optional
// 企业微信展示对外名称.
typedef NS_ENUM(NSInteger, WWKDiplayNameType) {
WWKDefaultName = 0, // 企业微信
WWKLocalName = 1 // 政务微信
};
/*! @brief 收到一个来自企业微信的请求,第三方应用程序处理完后调用sendResp向企业微信发送结果
*
* 收到一个来自企业微信的请求,异步处理完成后必须调用sendResp发送处理结果给企业微信。
* 目前并未使用。
* @param req 具体请求内容,是自动释放的
*/
- (void)onReq:(WWKBaseReq *)req;
/*! @brief 发送一个sendReq后,收到企业微信的回应
*
* 收到一个来自企业微信的处理结果。调用一次sendReq后会收到onResp。
* 可能收到的处理结果有WWKSendMessageResp等。
* @param resp 具体的回应内容,是自动释放的
*/
- (void)onResp:(WWKBaseResp *)resp;
/*! @brief SessionKey更新回调
*
* 需要设置updateSessionKeyIfNeeded:YES,并且满足企业微信sessionKey更新策略才会调用
* @param
*/
- (void)onSessionKeyUpdate:(NSString *)newSessionKey;
@end
#pragma mark - WWKApi
/*! @brief 企业微信Api接口函数类
*
* 该类封装了企业微信终端SDK的所有接口
*/
@interface WWKApi : NSObject
/*! @brief WWKApi的成员函数,向企业微信终端程序注册第三方应用。
*
* 需要在每次启动第三方应用程序时调用。第一次调用后,会在企业微信的可用应用列表中出现。
* iOS7及以上系统需要调起一次企业微信才会出现在企业微信的可用应用列表中。
* @attention 请保证在主线程中调用此函数
* @param appid 企业微信开发者ID
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)registerApp:(NSString *)appid;
/*! @brief WWKApi的成员函数,向企业微信终端程序注册第三方应用。
*
* 需要在每次启动第三方应用程序时调用。第一次调用后,会在企业微信的可用应用列表中出现。
* iOS7及以上系统需要调起一次企业微信才会出现在企业微信的可用应用列表中。
* @attention 请保证在主线程中调用此函数
* @param appid 第三方应用的appid
* @param scheme 当前app的scheme
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)registerAppID:(NSString *)appid schema:(NSString *)schema;
/*! @brief WWKApi的成员函数,向企业微信终端程序注册企业应用。
*
* 需要在每次启动第三方应用程序时调用。第一次调用后,会在企业微信的可用应用列表中出现。
* @see registerApp
* @param appid 企业微信开发者ID
* @param corpid 企业微信企业ID
* @param agentid 企业微信企业应用ID
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)registerApp:(NSString *)appid corpId:(NSString *)corpid agentId:(NSString *)agentid;
/*! @brief 是否必要时更新sessionKey,默认为NO
*
* @param url 企业微信根据安全策略自动更新sessionKey,如果有更新,会触发onSessionKeyUpdate:回调
*/
+ (void)updateSessionKeyIfNeeded:(BOOL)enable;
/*! @brief 处理企业微信通过URL启动App时传递的数据
*
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中调用。
* @param url 企业微信启动第三方应用时传递过来的URL
* @param delegate WWKApiDelegate对象,用来接收企业微信触发的消息。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)handleOpenURL:(NSURL *)url delegate:(id<WWKApiDelegate>) delegate;
/*! @brief 检查企业微信是否已被用户安装
*
* @return 企业微信已安装返回YES,未安装返回NO。
* @note 由于iOS系统的限制,在iOS9及以上系统检测企业微信是否安装,需要将企业微信的scheme"wxwork"(云端版本)及"wxworklocal"(本地部署版本)添加到工程的Info.plist中的LSApplicationQueriesSchemes白名单里,否则此方法总是会返回NO。
* 详情参考 https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl
*/
+ (BOOL)isAppInstalled;
/*! @brief 获取企业微信的itunes安装地址
*
* @return 企业微信的安装地址字符串。
*/
+ (NSString *)getAppInstallUrl;
/*! @brief 获取当前企业微信SDK的版本号
*
* @return 返回当前企业微信SDK的版本号
*/
+ (NSString *)getApiVersion;
/*! @brief 打开企业微信
*
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)openApp;
/*!
* @brief 启动登录流程。
* @param navigationController 当前页面的导航栏控制器
* @param state 第三方应用传入的值,登录成功后会透传给第三方应用
* @see WWKSSOReq
*/
+ (void)startSSOLogin:(NSString *)state fromNavigationController:(UINavigationController *)navigationController;
/*! @brief 发送请求到企业微信,等待企业微信返回onResp
*
* 函数调用后,会切换到企业微信的界面。第三方应用程序等待企业微信返回onResp。企业微信在异步处理完成后一定会调用onResp。支持以下类型
* WWKSendMessageReq等。
* @param req 具体的发送请求,在调用函数后,请自己释放。
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)sendReq:(WWKBaseReq *)req;
/*! @brief 收到企业微信onReq的请求,发送对应的应答给企业微信,并切换到企业微信界面
*
* 函数调用后,会切换到企业微信的界面。第三方应用程序收到企业微信onReq的请求,异步处理该请求,完成后必须调用该函数。
* 目前暂未使用
* @param resp 具体的应答内容,调用函数后,请自己释放
* @return 成功返回YES,失败返回NO。
*/
+ (BOOL)sendResp:(WWKBaseResp *)resp;
/*! @brief 获取当前企业微信展示名称
*
* @return 返回当前企业微信展示名称
*/
+ (WWKDiplayNameType)displayNameType;
/*! @brief 设置登录态返回的sessionKey
*
*/
+ (void)setSessionKey:(NSString *)sessionKey;
/*! @brief 初始化OpenData
*
* @以block的形式返回成功或者失败
*/
+(void)initOpenData:(void (^)(BOOL isSucc))completion;
/*! @brief 获取成员或者部门的详细信息
*
* @param 传入WWKOpenDataItem输入,SDK会获取部门或用户名并以block的形式返回
* 需要initOpenData返回成功后才能调用
* @see WWKOpenDataItem
*/
+(void)getOpenData:(NSArray<WWKOpenDataItem *> *)dataList completion:(void (^)(NSError *error,NSArray<WWKOpenDataItem *> *dataArray))completion;
@end
//
// WWKApiObject.h
// wxwork
//
// Created by WXWork on 16/5/25.
// Copyright © 2019年 Tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@class WWKBaseResp;
@protocol WWKApiSerializable <NSObject>
- (BOOL)deserializeWithDictionary:(NSDictionary *)dict;
@end
@interface WWKBaseObject : NSObject
@property (nonatomic, copy) NSString *bundleID;
@property (nonatomic, copy) NSString *bundleName;
@property (nonatomic, assign) NSUInteger sequence;
@property (nonatomic, readonly, nullable) NSData *serializedData;
@property (nonatomic, readonly, nullable) NSMutableDictionary *serializedDict;
+ (instancetype)deserializeWithData:(NSData *)data appid:(NSString *)appid;
@end
#pragma mark - WWKBaseReq
/*! @brief 该类为企业微信终端SDK所有请求类的基类
*
*/
@interface WWKBaseReq : WWKBaseObject
- (WWKBaseResp *)respObj; // 对应返回的结构
@end
#pragma mark - WWKBaseResp
extern const int WWKBaseRespErrCodeOK; // 操作成功
extern const int WWKBaseRespErrCodeCancelled; // 操作被取消
extern const int WWKBaseRespErrCodeFailed; // 操作失败
extern const int WWKBaseRespErrCodeNotSupported; // 操作不支持(不能识别请求)
extern const int WWKBaseRespErrCodeLowAppVer; // 操作不支持(用户安装的App版本过低)
extern const int WWKBaseRespErrCodeNoPrivileges; // 没有此API的调用权限
extern const int WWKBaseRespErrCodeInvalidCall; // 调用出错(例如传入参数不正确)
extern const int WWKBaseRespErrCodeNetWork; // 网络出错(例如请求超时)
extern const int WWKBaseRespErrCodeSessonKeyTimeOut; // sessionkey超时
/*! @brief 该类为企业微信终端SDK所有响应类的基类
*
*/
@interface WWKBaseResp : WWKBaseObject
/** 错误码 */
@property (nonatomic, assign) int errCode;
/** 错误提示字符串 */
@property (nonatomic, retain, nullable) NSString *errStr;
@end
#pragma mark - WWKSendMessageReq
/*!
* @brief 带在 @c WWKSendMessageReq 中的消息对象基类。实际必须使用其子类
*/
@interface WWKMessageAttachment : NSObject
@end
/*!
* @brief 文本消息
*/
@interface WWKMessageTextAttachment : WWKMessageAttachment
@property (nonatomic, copy) NSString *text;
@end
/*!
* @brief 文件消息
*/
@interface WWKMessageFileAttachment : WWKMessageAttachment
@property (nonatomic, copy) NSString *filename;
@property (nonatomic, copy, nullable) NSString *path;
@property (nonatomic, retain, nullable) NSData *data;
@end
/*!
* @brief 图片消息
*/
@interface WWKMessageImageAttachment : WWKMessageFileAttachment
@end
/*!
* @brief 视频消息
*/
@interface WWKMessageVideoAttachment : WWKMessageFileAttachment
@end
/*!
* @brief 链接消息
*/
@interface WWKMessageLinkAttachment : WWKMessageAttachment
@property (nonatomic, copy, nullable) NSString *title; // 不能超过512bytes
@property (nonatomic, copy, nullable) NSString *summary; // 不能超过1k
@property (nonatomic, copy, nullable) NSString *url;
@property (nonatomic, copy, nullable) NSString *iconurl;
@property (nonatomic, retain, nullable) NSData *icon; // 不能超过32K
// 是否使用带 shareTicket 的转发,只有注册了企业应用的agentid才有效;只能为单条转发,放在WWKMessageGroupAttachment中会被过滤
@property (nonatomic, assign) BOOL withShareTicket;
@property (nonatomic, copy, nullable) NSString *shareTicketState;
@end
/*!
* @brief 小程序消息
*/
@interface WWKMessageMiniAppAttachment : WWKMessageAttachment
@property (nonatomic, copy) NSString *userName; // 小程序username
@property (nonatomic, copy, nullable) NSString *path; // 小程序页面的路径
@property (nonatomic, strong, nullable) NSData *hdImageData; // 小程序预览图 不能超过128k
@property (nonatomic, copy, nullable) NSString *title; // 小程序 当前页title 不能超过512bytes
@end
/*!
* @brief 位置消息
*/
@interface WWKMessageLocationAttachment : WWKMessageAttachment
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *address;
@property (nonatomic, assign) double lat;
@property (nonatomic, assign) double lng;
@property (nonatomic, assign) double zoom;
@end
/*!
* @brief 单条聊天记录消息
*/
@interface WWKMessageAttachmentWrapper : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSDate *date;
@property (nonatomic, copy, nullable) NSString *avatarUrl;
@property (nonatomic, copy, nullable) NSData *avatarData;
@property (nonatomic, retain) WWKMessageAttachment *attachment;
@end
/*!
* @brief 聊天记录消息组
*/
@interface WWKMessageGroupAttachment : WWKMessageAttachment
@property (nonatomic, copy) NSArray<WWKMessageAttachmentWrapper *> *contents;
@property (nonatomic, copy) NSString *title;
@end
typedef NS_ENUM(NSUInteger, WWKOpenIdType) {
WWKOpenIdTypeUnKnown = 0,
WWKOpenIdTypeUser, // 成员
WWKOpenIdTypeDepartment //部门
};
@interface WWKOpenIdInfo : NSObject
@property (nonatomic, copy, nullable) NSString *openid;
@property (nonatomic, assign) WWKOpenIdType idType;
@end
/*! @brief 第三方程序发送消息至企业微信终端程序的消息结构体
*
* 第三方程序向企业微信发送信息需要传入WWKSendMessageReq结构体,信息类型包括文本消息和多媒体消息,
* 分别对应于text和message成员。调用该方法后,企业微信处理完信息会向第三方程序发送一个处理结果。
* @see WWKSendMessageResp
*/
@interface WWKSendMessageReq : WWKBaseReq <WWKApiSerializable>
/** 发送消息的多媒体内容
* @see WWKMessageAttachment
*/
@property (nonatomic, retain, nullable) WWKMessageAttachment *attachment;
@end
#pragma mark - WWKSendMessageResp
/*! @brief 企业微信终端向第三方程序返回的WWKSendMessageReq处理结果。
*
* 第三方程序向企业微信终端发送WWKSendMessageReq后,企业微信发送回来的处理结果,该结果用WWKSendMessageResp表示。
*/
@interface WWKSendMessageResp : WWKBaseResp <WWKApiSerializable>
@end
#pragma mark - WWKPickContactReq
/*! @brief 第三方程序从企业微信终端程序选人的消息结构体
*
* 本接口无需登录态,只能选择邮箱联系人。如果需要选择所有联系人,请使用WWKSelectContactReq接口
*
*
*/
@interface WWKPickContactReq : WWKBaseReq <WWKApiSerializable>
@property (nonatomic, copy) NSString *type;
@end
#pragma mark - WWKPickContactResp
@interface WWKContactInfo : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy, nullable) NSString *email;
@end
@interface WWKPickContactResp : WWKBaseResp <WWKApiSerializable>
@property (nonatomic, retain, nullable) NSArray<WWKContactInfo *> *contacts;
@end
#pragma mark - WWKOpenConversationReq
@interface WWKOpenConversationReq : WWKBaseReq <WWKApiSerializable>
@property (nonatomic, assign) uint64_t conversationType;
@property (nonatomic, assign) uint64_t conversationId;
@end
#pragma mark - WWKOpenConversationResp
@interface WWKOpenConversationResp : WWKBaseResp <WWKApiSerializable>
@end
#pragma mark - WWKSSOReq
@interface WWKSSOReq : WWKBaseReq <WWKApiSerializable>
@property (nonatomic, copy) NSString *state;
@end
@interface WWKSSOResp : WWKBaseResp <WWKApiSerializable>
@property (nonatomic, retain, nullable) NSString *state;
@property (nonatomic, retain, nullable) NSString *code;
@end
/*! @brief 第三方程序创建群聊并发送消息至企业微信终端程序的消息结构体(需登录态)
*
* 第三方程序向企业微信发送信息需要传入WWKSendMessageReq结构体,创建群聊成员的openid列表
* (只支持成员,不支持部门),当前登录态返回的openUserid,信息类型包括文本消息和多媒体消息,
* 分别对应于text和message成员。调用该方法后,企业微信处理完信息会向第三方程序发送一个处理结果。
* @see WWKOpenChatWithMessageResp
*/
@interface WWKOpenChatWithMessageReq : WWKBaseReq <WWKApiSerializable>
/** 发送消息的多媒体内容
* @see WWKMessageAttachment
*/
@property (nonatomic, retain, nullable) WWKMessageAttachment *attachment;
/** 发送消息的到新创建的群聊
* 暂不支持传入部门信息
*/
@property (nonatomic, retain, nullable) NSArray<NSString *> *userOpenidList;
/**
* 从后台登录获取的openUserid
*/
@property (nonatomic, retain, nullable) NSString *openUserid;
@end
#pragma mark - WWKOpenChatWithMessageResp
/*! @brief 企业微信终端向第三方程序返回的WWKOpenChatWithMessageReq处理结果。
*
* 第三方程序向企业微信终端发送WWKOpenChatWithMessageReq后,企业微信发送回来的处理结果,该结果用WWKOpenChatWithMessageResp表示。
*/
@interface WWKOpenChatWithMessageResp : WWKBaseResp <WWKApiSerializable>
@end
#pragma mark - WWKSelectContactReq
/*! @brief 第三方程序从企业微信终端程序选人的消息结构体(需登录态)
*
* 第三方程序向企业微信发送信息需要传入当前登录态返回的openUserid。调用该方法后,企业微信调起选人流程,结束后会向第三方程序发送一个处理结果。
* @see WWKSelectContactResp
*/
@interface WWKSelectContactReq : WWKBaseReq <WWKApiSerializable>
/**
* 从后台登录获取的openUserid,必须填写这个字段
*/
@property (nonatomic, retain) NSString *openUserid;
@end
#pragma mark - WWKSelectContactResp
/*! @brief 选人回包
*
* 从这个接口返回的数据不会带人名或部门名,需要调用getOpenData接口获取名字等详细信息
* 目前仅支持选择成员,暂不支持选择部门
*/
@interface WWKSelectContactResp : WWKBaseResp <WWKApiSerializable>
@property (nonatomic, retain, nullable) NSArray<WWKOpenIdInfo *> *openids;
@end
/*! @brief getOpenData接口使用的结构
* @param openid 部门或成员openid信息
* @param type 需要查询的类型,目前仅支持userName(用户名称)、userDepartment(用户主部门名称)以及userGender(用户性别)、departmentName(部门名称),其中userName、userDepartment、userGender在openid为用成员时有效,departmentName在openid为部门时有效
* @param data 传入时不需要填写,getOpenData返回会填充该字段
*/
@interface WWKOpenDataItem : NSObject
@property (nonatomic, copy) NSString *openid;
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy, nullable) NSString *data;
@end
#pragma mark - WWKSelectPrivilegedContactReq
/*! @brief 第三方程序从企业微信终端程序选人的消息结构体(需登录态)
*
* 选择范围限定为企业通讯录
* 只支持成员,若勾选部门,则对应展开勾选部门下的成员。
* 与WWKSelectContactReq接口的区分是,返回的选择范围,需要经过第三方权限过滤。只返回在可见范围的列表,而完整的列表存在ticket给第三方,用于jsapi/api接口调用。
* @see WWKSelectPrivilegedContactResp
*/
@interface WWKSelectPrivilegedContactReq : WWKBaseReq <WWKApiSerializable>
/**
* 从后台登录获取的loginOpenUserid,必须填写这个字段
* selectedOpenUserIds 预选用户openUserId列表
* selectedTickets 预选ticket列表
*/
@property (nonatomic, copy) NSString *loginOpenUserid;
@property (nonatomic, copy) NSArray<NSString *> *selectedOpenUserIds;
@property (nonatomic, copy) NSArray<NSString *> *selectedTickets;
@end
#pragma mark - WWKSelectPrivilegedContactResp
/*! @brief 选人回包
*
* openUserIdList 返回openid的列表
* selectedTicket 选择的集合Ticket,用于对该选择集合操作的调用凭证。
* expiresIn selectedTicket的有效期,单位为秒
* selectedUserCount 选择的集合Ticket包含的用户数
*/
@interface WWKSelectPrivilegedContactResp : WWKBaseResp <WWKApiSerializable>
@property (nonatomic, copy) NSArray<NSString *> *openUserIdList;
@property (nonatomic, copy) NSString *selectedTicket;
@property (nonatomic, assign) uint32_t expiresIn;
@property (nonatomic, assign) uint32_t selectedUserCount;
@end
#pragma mark - WWKCreateChatWithMsgReq
/*! @brief 新建群聊发消息(需登录态)
*
* 选人范围包括企业通讯录和外部联系人。
* 支持用户传入openUserId,和selectedTicket
* @see WWKCreateChatWithMsgResp
*/
@interface WWKCreateChatWithMsgReq : WWKBaseReq <WWKApiSerializable>
/**
* loginOpenUserid 从后台登录获取的loginOpenUserid,必须填写这个字段
* selectedOpenUserIdList 创建会话的企业通讯录成员信息,格式为字符串,内容为成员的openid列表(可以从WWKSelectPrivilegedContactResp获取),限定必须为应用的可见范围内。列表最多2000项。
* selectedTicketList 已选择的成员集合凭证列表,(可以从WWKSelectPrivilegedContactResp获取)。列表最多10个。
* attachment 消息内容结构体,支持文本、文件、图片、视频、链接、聊天内容,参考WWKMessageAttachment
* chatName 群聊名称
* state 透传参数,最长256,用于回调第三方应用创建群聊事件
*
*/
@property (nonatomic, copy) NSString *loginOpenUserid;
@property (nonatomic, copy) NSArray<NSString *> *selectedOpenUserIdList;
@property (nonatomic, copy) NSArray<NSString *> *selectedTicketList;
@property (nonatomic, retain) WWKMessageAttachment *attachment;
@property (nonatomic, copy, nullable) NSString *chatName;
@property (nonatomic, copy, nullable) NSString *state;
@end
#pragma mark - WWKCreateChatWithMsgResp
/*! @brief 新建群聊发消息回包
*
* errorCode 错误码
* errorMsg 错误码描述
* chatId 若创建群成功,返回群ID
*/
@interface WWKCreateChatWithMsgResp : WWKBaseResp <WWKApiSerializable>
@property (nonatomic, copy, nullable) NSString *chatId;
@end
#pragma mark - WWKOpenExistedChatWithMsgReq
/*! @brief 打开群聊发消息(需登录态)
*/
@interface WWKOpenExistedChatWithMsgReq : WWKBaseReq <WWKApiSerializable>
/**
* loginOpenUserid 从后台登录获取的loginOpenUserid,必须填写这个字段
* attachment 消息内容结构体,支持文本、文件、图片、视频、链接、聊天内容,参考WWKMessageAttachment attachment为可选。若不传参数,则无消息发送确认行为。
* chatId 打开群聊ID,chatId必须是当前用户所在的群聊
*
*/
@property (nonatomic, copy) NSString *loginOpenUserid;
@property (nonatomic, retain, nullable) WWKMessageAttachment *attachment;
@property (nonatomic, copy) NSString *chatId;
@end
#pragma mark - WWKOpenExistedChatWithMsgResp
/*! @brief 打开群聊发消息回包
*
* errorCode 错误码
* errorMsg 错误码描述
*/
@interface WWKOpenExistedChatWithMsgResp : WWKBaseResp <WWKApiSerializable>
@end
NS_ASSUME_NONNULL_END
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint flutter_wxwork.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'flutter_wxwork'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin project.'
s.description = <<-DESC
A new Flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = :ios, '9.0'
# s.dependency 'Classes/libWXWorkApi.a'
s.vendored_libraries = 'Classes/libWXWorkApi.a'
# 依赖的第三方库用到了静态库,还需要添加:
# s.static_framework = true
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
end
import 'dart:async';
import 'dart:io';
import 'package:flutter_wxwork/flutter_wxwork_method_channel.dart';
import 'flutter_wxwork_platform_interface.dart';
class FlutterWxwork {
Future<String?> getPlatformVersion() {
return FlutterWxworkPlatform.instance.getPlatformVersion();
}
Future<bool?> registerApp(scheme, corpId, agentId) {
return FlutterWxworkPlatform.instance.registerApp(scheme, corpId, agentId);
}
Future<AuthModel> auth({String state = 'state'}) async {
return FlutterWxworkPlatform.instance.auth();
}
Future<bool?> isAppInstalled() {
return FlutterWxworkPlatform.instance.isAppInstalled();
}
Future<bool?> shareImageNetWork(String path) {
return FlutterWxworkPlatform.instance.shareImageNetWork(path);
}
FutureOr<bool?> shareImagePath(String path) {
return FlutterWxworkPlatform.instance.shareImagePath(path);
}
Future<dynamic> shareMiniProgram(
{String? userName, //必须是应用关联的小程序,注意要有@app后缀
String? path,
String? hdImageData,
String title = "分享标题",
String description = ""}) {
return FlutterWxworkPlatform.instance.shareMiniProgram(
userName: userName, path: path, hdImageData: hdImageData, title: title,description:description);
}
Future<bool?> shareText({String text = "分享内容"}) {
return FlutterWxworkPlatform.instance.shareText(
text: text,
);
}
}
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'flutter_wxwork_platform_interface.dart';
/// An implementation of [FlutterWxworkPlatform] that uses method channels.
class MethodChannelFlutterWxwork extends FlutterWxworkPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
final methodChannel = const MethodChannel('flutter_wxwork');
@override
Future<String?> getPlatformVersion() async {
final version =
await methodChannel.invokeMethod<String>('getPlatformVersion');
return version;
}
@override
Future<bool?> registerApp(scheme, corpId, agentId) async {
bool? result =
await methodChannel.invokeMethod<bool>('register', <String, String>{
'scheme': scheme,
'corpId': corpId,
'agentId': agentId,
});
return result;
}
@override
Future<bool?> isAppInstalled() async {
final isAppInstalled =
await methodChannel.invokeMethod<bool>('isAppInstalled');
return isAppInstalled;
}
@override
Future<bool?> shareImageNetWork(String path) async {
final shareImageNetWork = await methodChannel
.invokeMethod<bool>('shareImageNetWork', <String, String>{
'path': path,
});
return shareImageNetWork;
}
@override
Future<bool?> shareImagePath(String path) async {
final shareImagePath = await methodChannel
.invokeMethod<bool>('shareImagePath', <String, String>{
'path': path,
});
return shareImagePath;
}
@override
Future<dynamic> shareMiniProgram(
{String? userName, //必须是应用关联的小程序,注意要有@app后缀
String? path,
String? hdImageData,
String title = "分享标题",
String description= ""}) async {
final shareMiniProgram = await methodChannel.invokeMethod<dynamic>(
'shareMiniProgram', <String, String?>{
'userName': userName,
'path': path,
'hdImageData': hdImageData,
'title': title,
"description":description
});
return shareMiniProgram;
}
@override
Future<bool?> shareText({String text = "分享内容"}) async {
final shareText =
await methodChannel.invokeMethod<bool>('shareText', <String, String>{
'text': text,
});
return shareText;
}
@override
Future<AuthModel> auth({String state = 'state'}) async {
var content = await methodChannel.invokeMethod('auth', {"state": state});
return AuthModel.fromJson(Map<String, dynamic>.from(content));
}
bool _stringToBool(String string) {
if (string == '1') {
return true;
} else {
return false;
}
}
}
class AuthModel {
/// 1.取消 0.成功 2.失败
String? errCode;
String? code;
String? state;
bool get isSuccess => errCode == '1';
AuthModel();
factory AuthModel.fromJson(Map<String, dynamic> json) {
AuthModel model = AuthModel();
model.errCode = json['errCode'];
model.code = json['code'];
model.state = json['state'];
return model;
}
Map<String, dynamic> toJson() {
return {'errorCode': errCode, 'code': code, 'state': state};
}
@override
String toString() {
return jsonEncode(this);
}
}
import 'dart:async';
import 'dart:io';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'flutter_wxwork_method_channel.dart';
abstract class FlutterWxworkPlatform extends PlatformInterface {
/// Constructs a FlutterWxworkPlatform.
FlutterWxworkPlatform() : super(token: _token);
static final Object _token = Object();
static FlutterWxworkPlatform _instance = MethodChannelFlutterWxwork();
/// The default instance of [FlutterWxworkPlatform] to use.
///
/// Defaults to [MethodChannelFlutterWxwork].
static FlutterWxworkPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [FlutterWxworkPlatform] when
/// they register themselves.
static set instance(FlutterWxworkPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<String?> getPlatformVersion() {
throw UnimplementedError('platformVersion() has not been implemented.');
}
Future<bool?> registerApp(scheme, corpId, agentId) {
throw UnimplementedError('registerApp() has not been implemented.');
}
Future<bool?> isAppInstalled() {
throw UnimplementedError('isAppInstalled() has not been implemented.');
}
Future<bool?> shareImageNetWork(String path) {
throw UnimplementedError('shareImageNetWork() has not been implemented.');
}
Future<bool?> shareImagePath(String path) {
throw UnimplementedError('shareImagePath() has not been implemented.');
}
Future<AuthModel> auth() {
throw UnimplementedError('auth() has not been implemented.');
}
Future<dynamic> shareMiniProgram(
{String? userName, //必须是应用关联的小程序,注意要有@app后缀
String? path,
String? hdImageData,
String title = "分享标题",
String description = ""}) {
throw UnimplementedError('shareMiniProgram() has not been implemented.');
}
Future<bool?> shareText({String text = "分享内容"}) {
throw UnimplementedError('shareText() has not been implemented.');
}
}
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
async:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.0"
fake_async:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.2"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
leak_tracker:
dependency: transitive
description:
name: leak_tracker
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.0.7"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.8"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
matcher:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.16+1"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.11.1"
meta:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.15.0"
path:
dependency: transitive
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.0"
plugin_platform_interface:
dependency: "direct main"
description:
name: plugin_platform_interface
sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.5"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_span:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.12.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
string_scanner:
dependency: transitive
description:
name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.3"
vector_math:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
vm_service:
dependency: transitive
description:
name: vm_service
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
url: "https://pub.flutter-io.cn"
source: hosted
version: "14.3.0"
sdks:
dart: ">=3.4.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
name: flutter_wxwork
description: A new Flutter plugin project.
version: 0.0.1
homepage:
environment:
sdk: '>=2.12.0 <3.0.0'
# flutter: ">=2.5.0"
dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
# which should be registered in the plugin registry. This is required for
# using method channels.
# The Android 'package' specifies package in which the registered class is.
# This is required for using method channels on Android.
# The 'ffiPlugin' specifies that native code should be built and bundled.
# This is required for using `dart:ffi`.
# All these are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
package: com.wxwork.flutter_wxwork
pluginClass: FlutterWxworkPlugin
ios:
pluginClass: FlutterWxworkPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_wxwork/flutter_wxwork_method_channel.dart';
void main() {
MethodChannelFlutterWxwork platform = MethodChannelFlutterWxwork();
const MethodChannel channel = MethodChannel('flutter_wxwork');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('getPlatformVersion', () async {
expect(await platform.getPlatformVersion(), '42');
});
}
// import 'package:flutter_test/flutter_test.dart';
// import 'package:flutter_wxwork/flutter_wxwork.dart';
// import 'package:flutter_wxwork/flutter_wxwork_platform_interface.dart';
// import 'package:flutter_wxwork/flutter_wxwork_method_channel.dart';
// import 'package:plugin_platform_interface/plugin_platform_interface.dart';
// class MockFlutterWxworkPlatform
// with MockPlatformInterfaceMixin
// implements FlutterWxworkPlatform {
// @override
// Future<String?> getPlatformVersion() => Future.value('42');
// }
// void main() {
// final FlutterWxworkPlatform initialPlatform = FlutterWxworkPlatform.instance;
// test('$MethodChannelFlutterWxwork is the default instance', () {
// expect(initialPlatform, isInstanceOf<MethodChannelFlutterWxwork>());
// });
// test('getPlatformVersion', () async {
// FlutterWxwork flutterWxworkPlugin = FlutterWxwork();
// MockFlutterWxworkPlatform fakePlatform = MockFlutterWxworkPlatform();
// FlutterWxworkPlatform.instance = fakePlatform;
// expect(await flutterWxworkPlugin.getPlatformVersion(), '42');
// });
// }
sdk.dir=/Users/naji2021/Library/Android/sdk
flutter.sdk=/Users/naji2021/Documents/flutter
\ No newline at end of file
flutter.sdk=/Users/naji2021/fvm/versions/3.27.3
\ No newline at end of file
... ...
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/naji2021/Documents/flutter
FLUTTER_ROOT=/Users/naji2021/fvm/versions/3.27.3
FLUTTER_APPLICATION_PATH=/Users/naji2021/Desktop/Flutter-ReserveApp/library/table_calendar-3.1.3/example
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
... ...
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/naji2021/Documents/flutter"
export "FLUTTER_ROOT=/Users/naji2021/fvm/versions/3.27.3"
export "FLUTTER_APPLICATION_PATH=/Users/naji2021/Desktop/Flutter-ReserveApp/library/table_calendar-3.1.3/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
... ...
sdk.dir=/Users/naji2021/Library/Android/sdk
flutter.sdk=/Users/naji2021/Documents/flutter
flutter.sdk=/Users/naji2021/fvm/versions/3.27.3
flutter.buildMode=debug
\ No newline at end of file
... ...
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=/Users/naji2021/Documents/flutter
FLUTTER_ROOT=/Users/naji2021/fvm/versions/3.27.3
FLUTTER_APPLICATION_PATH=/Users/naji2021/Desktop/Flutter-ReserveApp/library/webview_flutter-2.0.13-copy_inappwebview_select_file_20210930/example
COCOAPODS_PARALLEL_CODE_SIGN=true
FLUTTER_TARGET=lib/main.dart
... ...
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/naji2021/Documents/flutter"
export "FLUTTER_ROOT=/Users/naji2021/fvm/versions/3.27.3"
export "FLUTTER_APPLICATION_PATH=/Users/naji2021/Desktop/Flutter-ReserveApp/library/webview_flutter-2.0.13-copy_inappwebview_select_file_20210930/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
... ...
... ... @@ -927,13 +927,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_wxwork:
dependency: "direct main"
description:
path: "library/flutter_wxwork"
relative: true
source: path
version: "0.0.1"
fluttertoast:
dependency: "direct main"
description:
... ...
... ... @@ -226,8 +226,8 @@ dependencies:
path: library/sendsms-1.0.3
device_utils_my:
path: library/device_utils_my
flutter_wxwork:
path: library/flutter_wxwork
# flutter_wxwork:
# path: library/flutter_wxwork
calendar_date_picker2:
path: library/calendar_date_picker2-1.1.5
table_calendar:
... ...