project init

This commit is contained in:
Liuyf 2025-02-20 19:07:11 +08:00
parent c940e06abd
commit e86113eaff
89 changed files with 5528 additions and 76 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.idea/

197
CHANGELOG.md Normal file
View File

@ -0,0 +1,197 @@
## 2.5.8
修复onCommandResult 方法崩溃
## 2.5.7
修复onCommandResult 方法中没有 extra 参数问题都放到map中
## 2.5.6
修复清单文件少包名问题
## 2.5.5
修复后台不能获取回调的问题
## 2.5.4
修复在map中且套map不能获取数据问题
## 2.5.3
1、升级 iOS SDK JPush 5.3.0, 升级 android JPush 5.4.0
2、开放 setLinkMergeEnable、setGeofenceEnable、setSmartPushEnable、setCollectControl 接口设置
3、删除 setLbsEnable 接口设置
## 2.5.2
开放支持动态设置appkey
## 2.5.1
JPush 523
## 2.5.0
更新JCore 440 JPush 520
## 2.4.9
修复testCountryCode报错问题
## 2.4.8
修复不能清理本地通知问题
## 2.4.7
开放requestRequiredPermission API
## 2.4.6
开放setChannelAndSound API
## 2.4.5
+ 修复onConnected 崩溃问题
+ 升级:升级 Android+IOS JPush 5.0.4
升级 Android+IOS JCore 4.2.4
+ 新增setLbsEnable API
## 2.4.4
+ 修复:优化代码结构
## 2.4.3
+ 升级:升级 Android+IOS JPush 5.0.0
升级 Android+IOS JCore 4.2.0
+ 新增enableAutoWakeup API
## 2.4.2
开放 onConnected 回调
## 2.4.1
+ 升级:升级 Android JPush 4.9.0
升级 Android JCore 4.1.0
## 2.4.0
+ 升级:升级 Android JPush 4.8.4
## 2.3.9
+ 升级:升级 Android JPush 4.8.3
升级 Android JCore 3.3.6
## 2.3.8
+ 新增testCountryCode API
## 2.3.7
+ 升级:升级 Android JPush 4.8.1
升级 Android JCore 3.3.2
升级 IOS JPush 4.8.1
升级 IOS JCore 3.2.5
## 2.3.6
+ 新增:修复崩溃问题
## 2.3.5
+ 新增iOS新增getAlias接口实现
## 2.3.4
+ 升级:升级 Android JPush 4.7.2
升级 Android JCore 3.3.0
## 2.3.3
+ 升级:升级 Android JPush 4.7.0
## 2.3.2
+ 新增修复setAuth()方法问题
## 2.3.1
+ 新增iOS对外暴露setAuth()方法
## 2.3.0
+ 新增对外暴露setAuth()方法
修复:点开通知会默认跳转到主页问题
## 2.2.9
+ 升级:升级 Android JPush 4.6.6
## 2.2.8
+ 升级使用g版本
## 2.2.7
+ 升级:升级 Android JCore 3.2.4
## 2.2.6
+ 修复:自定义消息解析崩溃问题
## 2.2.5
+ 升级jpsuh 4.6.4 jcore 3.2.2
## 2.2.4
+ 修复iOS点击通知冷启动app不回调onOpenNotification问题
## 2.2.3
+ 升级jpsuh 4.6.0
## 2.2.2
+ 新增getAlias接口
## 2.2.1
+ 升级iOSjpush3.7.0->jpus4.4.0
## 2.2.0
+ 修复channel为null时,异常崩溃问题
## 2.1.9
+ 升级新增onNotifyMessageUnShow方法
## 2.1.8
+ 升级: jpush 4.4.5
## 2.1.7
+ 升级: jcore 3.1.0
## 2.1.6
+ 升级:升级 android push 4.4.0 jcore 3.0.0
## 2.1.5
+ 升级:升级 android push 4.2.8 jcore 2.9.0ios push 3.7.0jcore 2.7.1。
## 2.1.4
+ 新增Android push 新增 setWakeEnable 接口
## 2.1.2
+ 升级:升级 android push 4.0.8 jcore 2.8.2ios push 3.6.1jcore 2.6.2。
## 2.0.9
+ 适配:处理 demo 运行时报错。
## 2.0.7
+ 适配:适配 null safety
## 2.0.5
+ 升级android jcore 升级 2.7.8
## 2.0.3
+ 升级android push 升级4.0.6ios push 升级 3.5.2
## 2.0.1
+ 适配Flutter 2.0Flutter 2.0 以下版本请使用 0.6.3版本
## 0.6.3
+ 修复Android端获取RegistrationID偶现奔溃问题
## 0.6.2
+ 同步更最新版本SDK
## 0.6.1
+ 修复Android 端 context为空时的crash问题
## 0.6.0
+ 修复修复已知bug
## 0.5.9
+ 适配最新版本 JPush SDK Android 3.8.0 , IOS 3.3.6
## 0.5.6
+ 修复iOS点击本地通知的通知栏消息缺少extras 字段
## 0.5.5
+ 适配iOS点击本地通知的通知栏消息响应事件
+ 更新最新Android SDK
## 0.5.3
+ 修复一个可能引起崩溃的日志打印代码
## 0.5.2
+ 内部安全策略优化
+ 同步 JPush SDK 版本
## 0.5.1
+ 修改 minSdkVersion 最小支持 17
## 0.5.0
+ 适配最新版本 JPush SDK
+ 适配新版 SDK 的新功能接口
## 0.3.0
+ 新增:清除通知栏单条通知方法
+ 修复:点击通知栏无法获取消息问题
+ 同步最新版 SDK
## 0.2.0
+ 适配最新版本 JPush SDK
+ Android 支持设置角标 badge
## 0.1.0
+ 修复:调用 sendLocalNotification 接口 crash 问题;
+ 修复iOS 启动 APP 角标自动消失问题;
+ 修复执行 flutter build apk 打包错误问题;
+ 更新配置
## 0.0.13
featurn:
适配flutter 1.7.8
升级 jpush sdk 版本为3.3.4
## 0.0.12
featurn: 修改LocalNotification的属性名为"extra"
## 0.0.11
iOS: 修复 getLaunchAppNotification 返回 null 的情况。
featurn: APNS 推送字段将 extras 字段移动到 notification.extras 中和 android 保持一致。
## 0.0.9
android: 修复 JPushReceiver 类型转换的错误。
## 0.0.8
更新 setup 方法android 端现在支持 channel 字段,用于动态设置 channel和 iOS 保持一致。
注意通过 setup 设置 的 channel 会覆盖 manifestPlaceholders 中的 JPUSH_CHANNEL 字段。
## 0.0.7
修改 setup 方法,添加 boolean debug 参数,如果 debug 为 true 这打印日志,如果为 false 则不打印日志。
## 0.0.6
增加 swift 工程支持。
## 0.0.3
添加 localnotification api。
## 0.0.2
修复 android 类名文件名不匹配问题。
## 0.0.1
第一个版本。

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 极光开发者
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

120
README.md
View File

@ -1,93 +1,61 @@
# jpush_flutter_sdk
[![QQ Group](https://img.shields.io/badge/QQ%20Group-862401307-red.svg)]()
# JPush Flutter Plugin
### 安装
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
在工程 pubspec.yaml 中加入 dependencies
```
cd existing_repo
git remote add origin http://code-internal.star-lock.cn/liuyanfeng/jpush_flutter_sdk.git
git branch -M main
git push -uf origin main
//github 集成
dependencies:
jpush_flutter:
git:
url: git://github.com/jpush/jpush-flutter-plugin.git
ref: dev-2.x
// pub 集成
dependencies:
jpush_flutter: 2.5.8
```
## Integrate with your tools
### 配置
- [ ] [Set up project integrations](http://code-internal.star-lock.cn/liuyanfeng/jpush_flutter_sdk/-/settings/integrations)
##### Android:
## Collaborate with your team
`/android/app/build.gradle` 中添加下列代码:
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
```groovy
android: {
....
defaultConfig {
applicationId "替换成自己应用 ID"
...
ndk {
//选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a',
}
## Test and Deploy
manifestPlaceholders = [
JPUSH_PKGNAME : applicationId,
JPUSH_APPKEY : "appkey", // NOTE: JPush 上注册的包名对应的 Appkey.
JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
]
}
```
##### iOS:
Use the built-in continuous integration in GitLab.
- 在 xcode8 之后需要点开推送选项: TARGETS -> Capabilities -> Push Notification 设为 on 状态
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
### 使用
***
```dart
import 'package:jpush_flutter/jpush_flutter.dart';
```
# Editing this README
### APIs
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
**注意** : 需要先调用 JPush.setup 来初始化插件,才能保证其他功能正常工作。
## Suggestions for a good README
[参考](./documents/APIs.md)
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

BIN
android/.DS_Store vendored Normal file

Binary file not shown.

39
android/build.gradle Normal file
View File

@ -0,0 +1,39 @@
group 'com.jiguang.jpush'
version '1.0-SNAPSHOT'
buildscript {
repositories {
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
}
}
rootProject.allprojects {
repositories {
mavenCentral()
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 17
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation 'cn.jiguang.sdk:jpush:5.4.0'
}

View File

@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Fri Jul 26 11:14:36 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

160
android/gradlew vendored Normal file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
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" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@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
@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=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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 init
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 init
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
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
: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 %CMD_LINE_ARGS%
: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

1
android/settings.gradle Normal file
View File

@ -0,0 +1 @@
rootProject.name = 'jpush'

View File

@ -0,0 +1,41 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jiguang.jpush"
>
<application>
<!-- <receiver-->
<!-- android:name="com.jiguang.jpush.JPushPlugin$JPushReceiver"-->
<!-- android:enabled="true"-->
<!-- android:exported="false">-->
<!-- <intent-filter>-->
<!-- <action android:name="cn.jpush.android.intent.REGISTRATION" />-->
<!-- <action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" />-->
<!-- <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" />-->
<!-- <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" />-->
<!-- <action android:name="cn.jpush.android.intent.NOTIFICATION_CLICK_ACTION" />-->
<!-- <action android:name="cn.jpush.android.intent.CONNECTION" />-->
<!-- <category android:name="${applicationId}" />-->
<!-- </intent-filter>-->
<!-- </receiver>-->
<receiver android:name="com.jiguang.jpush.JPushEventReceiver"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
<!-- Since JCore2.0.0 Required SDK核心功能-->
<!-- 可配置android:process参数将Service放在其他进程中android:enabled属性不能是false -->
<!-- 这个是自定义Service要继承极光JCommonService可以在更多手机平台上使得推送通道保持的更稳定 -->
<service android:name=".JPushCustomService"
android:enabled="true"
android:exported="false"
android:stopWithTask="true"
android:process=":pushcore">
<intent-filter>
<action android:name="cn.jiguang.user.service.action" />
</intent-filter>
</service>
</application>
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE"/>
</manifest>

View File

@ -0,0 +1,6 @@
package com.jiguang.jpush;
import cn.jpush.android.service.JCommonService;
public class JPushCustomService extends JCommonService {
}

View File

@ -0,0 +1,238 @@
package com.jiguang.jpush;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import cn.jpush.android.api.CmdMessage;
import cn.jpush.android.api.CustomMessage;
import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.JPushMessage;
import cn.jpush.android.api.NotificationMessage;
import cn.jpush.android.service.JPushMessageReceiver;
import io.flutter.plugin.common.MethodChannel.Result;
public class JPushEventReceiver extends JPushMessageReceiver {
@Override
public void onNotifyMessageArrived(Context context, NotificationMessage notificationMessage) {
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().transmitNotificationReceive(notificationMessage);
}
});
}
@Override
public void onNotifyMessageOpened(Context context, NotificationMessage notificationMessage) {
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().transmitNotificationOpen(notificationMessage);
}
});
}
@Override
public void onMessage(Context context, CustomMessage customMessage) {
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().transmitMessageReceive(customMessage);
}
});
}
@Override
public void onRegister(Context context, String s) {
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().transmitReceiveRegistrationId(s);
}
});
}
@Override
public void onCommandResult(Context context,final CmdMessage cmdMessage) {
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().onCommandResult(cmdMessage);
}
});
}
@Override
public void onNotifyMessageUnShow(Context context,final NotificationMessage notificationMessage) {
super.onNotifyMessageUnShow(context,notificationMessage);
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().onNotifyMessageUnShow(notificationMessage);
}
});
}
@Override
public void onConnected(Context context,final boolean isConnected) {
//连接状态
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().onConnected(isConnected);
}
});
}
@Override
public void onInAppMessageShow(Context context,final NotificationMessage message) {
Log.i("JPushPlugin", "[onInAppMessageShow], " + message.toString());
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().onInAppMessageShow(message);
}
});
}
@Override
public void onInAppMessageClick(Context context,final NotificationMessage message) {
Log.i("JPushPlugin", "[onInAppMessageClick], " + message.toString());
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
JPushHelper.getInstance().onInAppMessageClick(message);
}
});
}
@Override
public void onTagOperatorResult(Context context, final JPushMessage jPushMessage) {
super.onTagOperatorResult(context, jPushMessage);
final JSONObject resultJson = new JSONObject();
final int sequence = jPushMessage.getSequence();
try {
resultJson.put("sequence", sequence);
} catch (JSONException e) {
e.printStackTrace();
}
final Result callback = JPushHelper.getInstance().getCallback(sequence);//instance.eventCallbackMap.get(sequence);
if (callback == null) {
Log.i("JPushPlugin", "Unexpected error, callback is null!");
return;
}
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
if (jPushMessage.getErrorCode() == 0) { // success
Set<String> tags = jPushMessage.getTags();
List<String> tagList = new ArrayList<>(tags);
Map<String, Object> res = new HashMap<>();
res.put("tags", tagList);
callback.success(res);
} else {
try {
resultJson.put("code", jPushMessage.getErrorCode());
} catch (JSONException e) {
e.printStackTrace();
}
callback.error(Integer.toString(jPushMessage.getErrorCode()), "", "");
}
JPushHelper.getInstance().removeCallback(sequence);
}
});
}
@Override
public void onCheckTagOperatorResult(Context context, final JPushMessage jPushMessage) {
super.onCheckTagOperatorResult(context, jPushMessage);
final int sequence = jPushMessage.getSequence();
final Result callback = JPushHelper.getInstance().getCallback(sequence);;
if (callback == null) {
Log.i("JPushPlugin", "Unexpected error, callback is null!");
return;
}
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
if (jPushMessage.getErrorCode() == 0) {
Set<String> tags = jPushMessage.getTags();
List<String> tagList = new ArrayList<>(tags);
Map<String, Object> res = new HashMap<>();
res.put("tags", tagList);
callback.success(res);
} else {
callback.error(Integer.toString(jPushMessage.getErrorCode()), "", "");
}
JPushHelper.getInstance().removeCallback(sequence);
}
});
}
@Override
public void onAliasOperatorResult(Context context, final JPushMessage jPushMessage) {
super.onAliasOperatorResult(context, jPushMessage);
final int sequence = jPushMessage.getSequence();
final Result callback = JPushHelper.getInstance().getCallback(sequence);;
if (callback == null) {
Log.i("JPushPlugin", "Unexpected error, callback is null!");
return;
}
JPushHelper.getInstance().getHandler().post(new Runnable() {
@Override
public void run() {
if (jPushMessage.getErrorCode() == 0) { // success
Map<String, Object> res = new HashMap<>();
res.put("alias", (jPushMessage.getAlias() == null)? "" : jPushMessage.getAlias());
callback.success(res);
} else {
callback.error(Integer.toString(jPushMessage.getErrorCode()), "", "");
}
JPushHelper.getInstance().removeCallback(sequence);
}
});
}
@Override
public void onNotificationSettingsCheck(Context context, boolean isOn, int source) {
super.onNotificationSettingsCheck(context, isOn, source);
HashMap<String, Object> map = new HashMap();
map.put("isEnabled",isOn);
JPushHelper.getInstance().runMainThread(map,null,"onReceiveNotificationAuthorization");
}
}

View File

@ -0,0 +1,363 @@
package com.jiguang.jpush;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import cn.jpush.android.api.CmdMessage;
import cn.jpush.android.api.CustomMessage;
import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.NotificationMessage;
import cn.jpush.android.local.JPushConstants;
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;
public class JPushHelper {
private static String TAG = "| JPUSH | Flutter | Android | ";
private List<Map<String, Object>> openNotificationCache = new ArrayList<>();
private boolean dartIsReady = false;
private boolean jpushDidinit = false;
private Handler mHandler;
private List<Result> getRidCache = new ArrayList<>();
private MethodChannel channel;
private Map<Integer, Result> callbackMap = new HashMap<>();
private WeakReference<Context> mContext;
private JPushHelper() {
}
private static final class SingleHolder {
private static final JPushHelper single = new JPushHelper();
}
public static JPushHelper getInstance() {
return SingleHolder.single;
}
public MethodChannel getChannel() {
return channel;
}
public Result getCallback(int sequence) {
return callbackMap.get(sequence);
}
public void addCallback(int sequence, Result result) {
callbackMap.put(sequence, result);
}
public void removeCallback(int sequence) {
callbackMap.remove(sequence);
}
public void addRid(Result result) {
getRidCache.add(result);
}
public Handler getHandler() {
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
return mHandler;
}
public void setMethodChannel(MethodChannel channel) {
this.channel = channel;
}
public void setContext(Context context) {
if (mContext != null) {
mContext.clear();
mContext = null;
}
mContext = new WeakReference<>(context.getApplicationContext());
mHandler = new Handler(Looper.getMainLooper());
}
public void setDartIsReady(boolean isReady) {
dartIsReady = isReady;
}
public void setJpushDidinit(boolean jpushDidinit) {
this.jpushDidinit = jpushDidinit;
}
public void dispatchNotification() {
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
List<Object> tempList = new ArrayList<Object>();
if (dartIsReady) {
// try to shedule notifcation cache
List<Map<String, Object>> openNotificationCacheList = openNotificationCache;
for (Map<String, Object> notification : openNotificationCacheList) {
channel.invokeMethod("onOpenNotification", notification);
tempList.add(notification);
}
openNotificationCacheList.removeAll(tempList);
tempList.clear();
}
}
public void dispatchRid() {
if (mContext == null || mContext.get() == null) {
return;
}
List<Object> tempList = new ArrayList<Object>();
String rid = JPushInterface.getRegistrationID(mContext.get());
boolean ridAvailable = rid != null && !rid.isEmpty();
if (ridAvailable && dartIsReady) {
// try to schedule get rid cache
tempList.clear();
List<Result> resultList = getRidCache;
for (Result res : resultList) {
Log.d(TAG, "scheduleCache rid = " + rid);
res.success(rid);
tempList.add(res);
}
resultList.removeAll(tempList);
tempList.clear();
}
}
public void transmitMessageReceive(CustomMessage customMessage) {
Log.d(TAG, "transmitMessageReceive " + "customMessage=" + customMessage);
if (channel == null) {
Log.d(TAG, "the instance is null");
return;
}
Map<String, Object> msg = new HashMap<>();
msg.put("message", customMessage.message);
msg.put("alert", customMessage.title);
msg.put("extras", getExtras(customMessage));
Log.d(TAG, "transmitMessageReceive msg=" + msg);
channel.invokeMethod("onReceiveMessage", msg);
}
public void transmitNotificationOpen(NotificationMessage notificationMessage) {
Log.d(TAG, "transmitNotificationOpen notificationMessage=" + notificationMessage);
Map<String, Object> notification = new HashMap<>();
notification.put("title", notificationMessage.notificationTitle);
notification.put("alert", notificationMessage.notificationContent);
notification.put("extras", getExtras(notificationMessage));
openNotificationCache.add(notification);
Log.d(TAG, "transmitNotificationOpen notification=" + notification);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Log.d(TAG, "instance.dartIsReady =" + dartIsReady);
if (dartIsReady) {
channel.invokeMethod("onOpenNotification", notification);
openNotificationCache.remove(notification);
}
}
public void transmitNotificationReceive(NotificationMessage notificationMessage) {
Log.d(TAG, "transmitNotificationReceive notificationMessage=" + notificationMessage);
// Log.d(TAG, "transmitNotificationReceive " + "title=" + title + "alert=" + alert + "extras=" + extras);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> notification = new HashMap<>();
notification.put("title", notificationMessage.notificationTitle);
notification.put("alert", notificationMessage.notificationContent);
notification.put("extras", getExtras(notificationMessage));
Log.d(TAG, "transmitNotificationReceive notification=" + notification);
channel.invokeMethod("onReceiveNotification", notification);
}
public void onCommandResult(CmdMessage cmdMessage) {
Log.e(TAG, "[onCommandResult] message:" + cmdMessage);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> notification = new HashMap<>();
notification.put("cmd", cmdMessage.cmd);
notification.put("errorCode", cmdMessage.errorCode);
notification.put("msg", cmdMessage.msg);
notification.put("extras", bundleToMap(cmdMessage.extra));
channel.invokeMethod("onCommandResult", notification);
}
public void onNotifyMessageUnShow(NotificationMessage notificationMessage) {
Log.e(TAG, "[onNotifyMessageUnShow] message:" + notificationMessage);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> notification = new HashMap<>();
notification.put("title", notificationMessage.notificationTitle);
notification.put("alert", notificationMessage.notificationContent);
notification.put("extras", getExtras(notificationMessage));
channel.invokeMethod("onNotifyMessageUnShow", notification);
}
public void onConnected(boolean isConnected) {
Log.e(TAG, "[onConnected] :" + isConnected);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> results = new HashMap<>();
results.put("result", isConnected);
channel.invokeMethod("onConnected", results);
}
public void onInAppMessageShow(NotificationMessage notificationMessage) {
Log.e(TAG, "[onInAppMessageShow] :" + notificationMessage);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> notification = new HashMap<>();
notification.put("title", notificationMessage.inAppMsgTitle);
notification.put("alert", notificationMessage.inAppMsgContentBody);
notification.put("messageId", notificationMessage.msgId);
notification.put("inAppShowTarget", notificationMessage.inAppShowTarget);
notification.put("inAppClickAction", notificationMessage.inAppClickAction);
notification.put("inAppExtras", stringToMap(notificationMessage.inAppExtras));
channel.invokeMethod("onInAppMessageShow", notification);
}
public void onInAppMessageClick(NotificationMessage notificationMessage) {
Log.e(TAG, "[onInAppMessageClick] :" + notificationMessage);
if (channel == null) {
Log.d(TAG, "the channel is null");
return;
}
Map<String, Object> notification = new HashMap<>();
notification.put("title", notificationMessage.inAppMsgTitle);
notification.put("alert", notificationMessage.inAppMsgContentBody);
notification.put("messageId", notificationMessage.msgId);
notification.put("inAppShowTarget", notificationMessage.inAppShowTarget);
notification.put("inAppClickAction", notificationMessage.inAppClickAction);
notification.put("inAppExtras", stringToMap(notificationMessage.inAppExtras));
channel.invokeMethod("onInAppMessageClick", notification);
}
private Map<String, Object> getExtras(CustomMessage customMessage) {
Map<String, Object> extra = new HashMap<>();
extra.put(JPushInterface.EXTRA_EXTRA, stringToMap(customMessage.extra));
extra.put(JPushInterface.EXTRA_MSG_ID, customMessage.messageId);
extra.put(JPushInterface.EXTRA_CONTENT_TYPE, customMessage.contentType);
if (JPushConstants.SDK_VERSION_CODE >= 387) {
extra.put(JPushInterface.EXTRA_TYPE_PLATFORM, customMessage.platform);
}
return extra;
}
private Map<String, Object> getExtras(NotificationMessage notificationMessage) {
Map<String, Object> extras = new HashMap<>();
try {
extras.put(JPushInterface.EXTRA_MSG_ID, notificationMessage.msgId);
extras.put(JPushInterface.EXTRA_NOTIFICATION_ID, notificationMessage.notificationId);
extras.put(JPushInterface.EXTRA_ALERT_TYPE, notificationMessage.notificationAlertType + "");
extras.put(JPushInterface.EXTRA_EXTRA, stringToMap(notificationMessage.notificationExtras));
if (notificationMessage.notificationStyle == 1 && !TextUtils.isEmpty(notificationMessage.notificationBigText)) {
extras.put(JPushInterface.EXTRA_BIG_TEXT, notificationMessage.notificationBigText);
} else if (notificationMessage.notificationStyle == 2 && !TextUtils.isEmpty(notificationMessage.notificationInbox)) {
extras.put(JPushInterface.EXTRA_INBOX, notificationMessage.notificationInbox);
} else if ((notificationMessage.notificationStyle == 3) && !TextUtils.isEmpty(notificationMessage.notificationBigPicPath)) {
extras.put(JPushInterface.EXTRA_BIG_PIC_PATH, notificationMessage.notificationBigPicPath);
}
if (!(notificationMessage.notificationPriority == 0)) {
extras.put(JPushInterface.EXTRA_NOTI_PRIORITY, notificationMessage.notificationPriority + "");
}
if (!TextUtils.isEmpty(notificationMessage.notificationCategory)) {
extras.put(JPushInterface.EXTRA_NOTI_CATEGORY, notificationMessage.notificationCategory);
}
if (!TextUtils.isEmpty(notificationMessage.notificationSmallIcon)) {
extras.put(JPushInterface.EXTRA_NOTIFICATION_SMALL_ICON, notificationMessage.notificationSmallIcon);
}
if (!TextUtils.isEmpty(notificationMessage.notificationLargeIcon)) {
extras.put(JPushInterface.EXTRA_NOTIFICATION_LARGET_ICON, notificationMessage.notificationLargeIcon);
}
} catch (Throwable e) {
Log.e(TAG, "[onNotifyMessageUnShow] e:" + e.getMessage());
}
return extras;
}
public static Map<String, Object> bundleToMap(Bundle bundle) {
Map<String, Object> map = new HashMap<>();
if (bundle != null) {
for (String key : bundle.keySet()) {
if("intent_component".equals(key)||"intent_action".equals(key)){
continue;
}
Object value = bundle.get(key);
map.put(key, value);
}
}
return map;
}
public Map<String, Object> stringToMap(String extra) {
Map<String, Object> useExtra = new HashMap<String, Object>();
try {
if (TextUtils.isEmpty(extra)) {
return useExtra;
}
JSONObject object = new JSONObject(extra);
Iterator<String> keys = object.keys();
while (keys.hasNext()) {
String key = keys.next();
Object value = object.get(key);
useExtra.put(key, value);
}
} catch (Throwable throwable) {
}
return useExtra;
}
public void transmitReceiveRegistrationId(String rId) {
Log.d(TAG, "transmitReceiveRegistrationId " + rId);
jpushDidinit = true;
dispatchNotification();
dispatchRid();
}
// 主线程再返回数据
public void runMainThread(final Map<String, Object> map, final Result result, final String method) {
Log.d(TAG, "runMainThread:" + "map = " + map + ",method =" + method);
getHandler().post(new Runnable() {
@Override
public void run() {
if (result == null && method != null) {
if (null != channel) {
channel.invokeMethod(method, map);
} else {
Log.d(TAG, "channel is null do nothing");
}
} else {
result.success(map);
}
}
});
}
}

View File

@ -0,0 +1,618 @@
package com.jiguang.jpush;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import cn.jpush.android.data.JPushConfig;
import cn.jiguang.api.JCoreInterface;
import cn.jiguang.api.utils.JCollectionAuth;
import cn.jpush.android.api.JPushInterface;
import cn.jpush.android.api.NotificationMessage;
import cn.jpush.android.data.JPushCollectControl;
import cn.jpush.android.data.JPushLocalNotification;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
/**
* JPushPlugin
*/
public class JPushPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware {
private static String TAG = "| JPUSH | Flutter | Android | ";
private Context context;
private Activity mActivity;
private int sequence;
public JPushPlugin() {
this.sequence = 0;
}
@Override
public void onAttachedToEngine(FlutterPluginBinding flutterPluginBinding) {
MethodChannel channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "jpush");
channel.setMethodCallHandler(this);
context = flutterPluginBinding.getApplicationContext();
JPushHelper.getInstance().setMethodChannel(channel);
JPushHelper.getInstance().setContext(context);
}
@Override
public void onAttachedToActivity(ActivityPluginBinding activityPluginBinding) {
if(activityPluginBinding!=null){
mActivity = activityPluginBinding.getActivity();
}
}
@Override
public void onDetachedFromActivityForConfigChanges() {
}
@Override
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding activityPluginBinding) {
}
@Override
public void onDetachedFromActivity() {
}
@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
MethodChannel channel =JPushHelper.getInstance().getChannel();
if(channel!=null){
channel.setMethodCallHandler(null);
}
JPushHelper.getInstance().setDartIsReady(false);
}
@Override
public void onMethodCall(MethodCall call, Result result) {
Log.i(TAG, call.method);
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("setup")) {
setup(call, result);
} else if (call.method.equals("setTags")) {
setTags(call, result);
} else if (call.method.equals("cleanTags")) {
cleanTags(call, result);
} else if (call.method.equals("addTags")) {
addTags(call, result);
} else if (call.method.equals("deleteTags")) {
deleteTags(call, result);
} else if (call.method.equals("getAllTags")) {
getAllTags(call, result);
} else if (call.method.equals("setAlias")) {
setAlias(call, result);
} else if (call.method.equals("getAlias")) {
getAlias(call, result);
} else if (call.method.equals("deleteAlias")) {
deleteAlias(call, result);
;
} else if (call.method.equals("stopPush")) {
stopPush(call, result);
} else if (call.method.equals("resumePush")) {
resumePush(call, result);
} else if (call.method.equals("clearAllNotifications")) {
clearAllNotifications(call, result);
}else if (call.method.equals("clearLocalNotifications")) {
clearLocalNotifications(call, result);
} else if (call.method.equals("clearNotification")) {
clearNotification(call, result);
} else if (call.method.equals("getLaunchAppNotification")) {
getLaunchAppNotification(call, result);
} else if (call.method.equals("getRegistrationID")) {
getRegistrationID(call, result);
} else if (call.method.equals("sendLocalNotification")) {
sendLocalNotification(call, result);
} else if (call.method.equals("setBadge")) {
setBadge(call, result);
} else if (call.method.equals("isNotificationEnabled")) {
isNotificationEnabled(call, result);
} else if (call.method.equals("openSettingsForNotification")) {
openSettingsForNotification(call, result);
} else if (call.method.equals("setWakeEnable")) {
setWakeEnable(call, result);
} else if (call.method.equals("setAuth")) {
setAuth(call, result);
} else if (call.method.equals("testCountryCode")) {
testCountryCode(call, result);
}else if (call.method.equals("enableAutoWakeup")) {
enableAutoWakeup(call, result);
} else if (call.method.equals("setLinkMergeEnable")) {
setLinkMergeEnable(call, result);
} else if (call.method.equals("setGeofenceEnable")) {
setGeofenceEnable(call, result);
} else if (call.method.equals("setSmartPushEnable")) {
setSmartPushEnable(call, result);
}else if (call.method.equals("setCollectControl")) {
setCollectControl(call, result);
}else if (call.method.equals("setChannelAndSound")) {
setChannelAndSound(call, result);
}else if (call.method.equals("requestRequiredPermission")) {
requestRequiredPermission(call, result);
} else {
result.notImplemented();
}
}
public void requestRequiredPermission(MethodCall call, Result result){
JPushInterface.requestRequiredPermission(mActivity);
}
public void setChannelAndSound(MethodCall call, Result result) {
HashMap<String, Object> readableMap = call.arguments();
if (readableMap == null) {
return;
}
String channel = (String)readableMap.get("channel");
String channelId = (String)readableMap.get("channel_id");
String sound = (String)readableMap.get("sound");
try {
NotificationManager manager= (NotificationManager) context.getSystemService("notification");
if(Build.VERSION.SDK_INT<26){
return;
}
if(TextUtils.isEmpty(channel)||TextUtils.isEmpty(channelId)){
return;
}
NotificationChannel channel1=new NotificationChannel(channelId,channel, NotificationManager.IMPORTANCE_HIGH);
if(!TextUtils.isEmpty(sound)){
channel1.setSound(Uri.parse("android.resource://"+context.getPackageName()+"/raw/"+sound),null);
}
manager.createNotificationChannel(channel1);
JPushInterface.setChannel(context,channel);
Log.d(TAG,"setChannelAndSound channelId="+channelId+" channel="+channel+" sound="+sound);
}catch (Throwable throwable){
}
}
private void setLinkMergeEnable(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = true;
}
JPushInterface.setLinkMergeEnable(context,enable);
}
private void setGeofenceEnable(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = true;
}
JPushInterface.setGeofenceEnable(context,enable);
}
private void setSmartPushEnable(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = true;
}
JPushInterface.setSmartPushEnable(context,enable);
}
private void setCollectControl(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
JPushCollectControl.Builder builder=new JPushCollectControl.Builder();
boolean hadValue=false;
if(map.containsKey("imsi")){
Boolean imsi = (Boolean) map.get("imsi");
builder.imsi(imsi);
hadValue=true;
}
if(map.containsKey("mac")){
Boolean mac = (Boolean) map.get("mac");
builder.mac(mac);
hadValue=true;
}
if(map.containsKey("wifi")){
Boolean wifi = (Boolean) map.get("wifi");
builder.wifi(wifi);
hadValue=true;
}
if(map.containsKey("bssid")){
Boolean bssid = (Boolean) map.get("bssid");
builder.bssid(bssid);
hadValue=true;
}
if(map.containsKey("ssid")){
Boolean ssid = (Boolean) map.get("ssid");
builder.ssid(ssid);
hadValue=true;
}
if(map.containsKey("imei")){
Boolean imei = (Boolean) map.get("imei");
builder.imei(imei);
hadValue=true;
}
if(map.containsKey("cell")){
Boolean cell = (Boolean) map.get("cell");
builder.cell(cell);
hadValue=true;
}
if(hadValue){
JPushInterface.setCollectControl(context,builder.build());
}
}
private void setAuth(MethodCall call, Result result){
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = false;
}
JCollectionAuth.setAuth(context,enable);
}
private void testCountryCode(MethodCall call, Result result){
String code = call.arguments();
Log.d(TAG,"testCountryCode code="+code);
JCoreInterface.testCountryCode(context,code);
}
private void setWakeEnable(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = false;
}
JCoreInterface.setWakeEnable(context,enable);
}
private void enableAutoWakeup(MethodCall call, Result result) {
HashMap<String, Object> map = call.arguments();
if (map == null) {
return;
}
Boolean enable = (Boolean) map.get("enable");
if (enable == null) {
enable = false;
}
JCollectionAuth.enableAutoWakeup(context,enable);
}
public void setup(MethodCall call, Result result) {
Log.d(TAG, "setup :" + call.arguments);
HashMap<String, Object> map = call.arguments();
boolean debug = (boolean) map.get("debug");
JPushInterface.setDebugMode(debug);
String appKey = (String) map.get("appKey");
if(!TextUtils.isEmpty(appKey)){
JPushConfig config=new JPushConfig();
config.setjAppKey(appKey);
JPushInterface.init(context,config);
}else {
JPushInterface.init(context);
} // 初始化 JPush
JPushInterface.setNotificationCallBackEnable(context, true);
String channel = (String) map.get("channel");
JPushInterface.setChannel(context, channel);
JPushHelper.getInstance().setDartIsReady(true);
// try to clean getRid cache
scheduleCache();
}
public void scheduleCache() {
Log.d(TAG, "scheduleCache:");
JPushHelper.getInstance().dispatchNotification();
JPushHelper.getInstance().dispatchRid();
}
public void setTags(MethodCall call, Result result) {
Log.d(TAG, "setTags");
List<String> tagList = call.arguments();
Set<String> tags = new HashSet<>(tagList);
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.setTags(context, sequence, tags);
}
public void cleanTags(MethodCall call, Result result) {
Log.d(TAG, "cleanTags:");
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.cleanTags(context, sequence);
}
public void addTags(MethodCall call, Result result) {
Log.d(TAG, "addTags: " + call.arguments);
List<String> tagList = call.arguments();
Set<String> tags = new HashSet<>(tagList);
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.addTags(context, sequence, tags);
}
public void deleteTags(MethodCall call, Result result) {
Log.d(TAG, "deleteTags " + call.arguments);
List<String> tagList = call.arguments();
Set<String> tags = new HashSet<>(tagList);
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.deleteTags(context, sequence, tags);
}
public void getAllTags(MethodCall call, Result result) {
Log.d(TAG, "getAllTags ");
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.getAllTags(context, sequence);
}
public void getAlias(MethodCall call, Result result) {
Log.d(TAG, "getAlias ");
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.getAlias(context, sequence);
}
public void setAlias(MethodCall call, Result result) {
Log.d(TAG, "setAlias: " + call.arguments);
String alias = call.arguments();
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.setAlias(context, sequence, alias);
}
public void deleteAlias(MethodCall call, Result result) {
Log.d(TAG, "deleteAlias:");
String alias = call.arguments();
sequence += 1;
JPushHelper.getInstance().addCallback(sequence,result);
JPushInterface.deleteAlias(context, sequence);
}
public void stopPush(MethodCall call, Result result) {
Log.d(TAG, "stopPush:");
JPushInterface.stopPush(context);
}
public void resumePush(MethodCall call, Result result) {
Log.d(TAG, "resumePush:");
JPushInterface.resumePush(context);
}
public void clearAllNotifications(MethodCall call, Result result) {
Log.d(TAG, "clearAllNotifications: ");
JPushInterface.clearAllNotifications(context);
}
public void clearLocalNotifications(MethodCall call, Result result) {
Log.d(TAG, "clearLocalNotifications: ");
JPushInterface.clearLocalNotifications(context);
}
public void clearNotification(MethodCall call, Result result) {
Log.d(TAG, "clearNotification: ");
Object id = call.arguments;
if (id != null) {
JPushInterface.clearNotificationById(context, (int) id);
}
}
public void getLaunchAppNotification(MethodCall call, Result result) {
Log.d(TAG, "");
}
public void getRegistrationID(MethodCall call, Result result) {
Log.d(TAG, "getRegistrationID: ");
if (context == null) {
Log.d(TAG, "register context is nil.");
return;
}
String rid = JPushInterface.getRegistrationID(context);
if (rid == null || rid.isEmpty()) {
JPushHelper.getInstance().addRid(result);
} else {
result.success(rid);
}
}
public void sendLocalNotification(MethodCall call, Result result) {
Log.d(TAG, "sendLocalNotification: " + call.arguments);
try {
HashMap<String, Object> map = call.arguments();
JPushLocalNotification ln = new JPushLocalNotification();
ln.setBuilderId((Integer) map.get("buildId"));
ln.setNotificationId((Integer) map.get("id"));
ln.setTitle((String) map.get("title"));
ln.setContent((String) map.get("content"));
HashMap<String, Object> extra = (HashMap<String, Object>) map.get("extra");
if (extra != null) {
JSONObject json = new JSONObject(extra);
ln.setExtras(json.toString());
}
long date = (long) map.get("fireTime");
ln.setBroadcastTime(date);
JPushInterface.addLocalNotification(context, ln);
} catch (Exception e) {
e.printStackTrace();
}
}
public void setBadge(MethodCall call, Result result) {
Log.d(TAG, "setBadge: " + call.arguments);
HashMap<String, Object> map = call.arguments();
Object numObject = map.get("badge");
if (numObject != null) {
int num = (int) numObject;
JPushInterface.setBadgeNumber(context, num);
result.success(true);
}
}
/// 检查当前应用的通知开关是否开启
private void isNotificationEnabled(MethodCall call, Result result) {
Log.d(TAG, "isNotificationEnabled: ");
int isEnabled = JPushInterface.isNotificationEnabled(context);
//1表示开启0表示关闭-1表示检测失败
HashMap<String, Object> map = new HashMap();
map.put("isEnabled", isEnabled == 1 ? true : false);
JPushHelper.getInstance().runMainThread(map, result, null);
}
private void openSettingsForNotification(MethodCall call, Result result) {
Log.d(TAG, "openSettingsForNotification: ");
JPushInterface.goToAppNotificationSettings(context);
}
/**
* 接收自定义消息,通知,通知点击事件等事件的广播
* 文档链接:http://docs.jiguang.cn/client/android_api/
*/
// public static class JPushReceiver extends BroadcastReceiver {
//
// private static final List<String> IGNORED_EXTRAS_KEYS = Arrays.asList("cn.jpush.android.TITLE",
// "cn.jpush.android.MESSAGE", "cn.jpush.android.APPKEY", "cn.jpush.android.NOTIFICATION_CONTENT_TITLE", "key_show_entity", "platform");
//
// public JPushReceiver() {
// }
//
//
// @Override
// public void onReceive(Context context, Intent intent) {
// String action = intent.getAction();
//
// if (action.equals(JPushInterface.ACTION_REGISTRATION_ID)) {
// String rId = intent.getStringExtra(JPushInterface.EXTRA_REGISTRATION_ID);
// Log.d("JPushPlugin", "on get registration");
// JPushHelper.getInstance().transmitReceiveRegistrationId(rId);
//
// } else if (action.equals(JPushInterface.ACTION_MESSAGE_RECEIVED)) {
// handlingMessageReceive(intent);
// } else if (action.equals(JPushInterface.ACTION_NOTIFICATION_RECEIVED)) {
// handlingNotificationReceive(context, intent);
// } else if (action.equals(JPushInterface.ACTION_NOTIFICATION_OPENED)) {
// handlingNotificationOpen(context, intent);
// }
// }
//
// private void handlingMessageReceive(Intent intent) {
// Log.d(TAG, "handlingMessageReceive " + intent.getAction());
//
// String msg = intent.getStringExtra(JPushInterface.EXTRA_MESSAGE);
// String title = intent.getStringExtra(JPushInterface.EXTRA_TITLE);
// Map<String, Object> extras = getNotificationExtras(intent);
// JPushHelper.getInstance().transmitMessageReceive(msg, title,extras);
// }
//
// private void handlingNotificationOpen(Context context, Intent intent) {
// Log.d(TAG, "handlingNotificationOpen " + intent.getAction());
//
// String title = intent.getStringExtra(JPushInterface.EXTRA_NOTIFICATION_TITLE);
// String alert = intent.getStringExtra(JPushInterface.EXTRA_ALERT);
// Map<String, Object> extras = getNotificationExtras(intent);
// JPushHelper.getInstance().transmitNotificationOpen(title, alert, extras);
// }
//
// private void handlingNotificationReceive(Context context, Intent intent) {
// Log.d(TAG, "handlingNotificationReceive " + intent.getAction());
//
// String title = intent.getStringExtra(JPushInterface.EXTRA_NOTIFICATION_TITLE);
// String alert = intent.getStringExtra(JPushInterface.EXTRA_ALERT);
// Map<String, Object> extras = getNotificationExtras(intent);
// JPushHelper.getInstance().transmitNotificationReceive(title, alert, extras);
// }
//
// private Map<String, Object> getNotificationExtras(Intent intent) {
// Map<String, Object> extrasMap = new HashMap<String, Object>();
// Bundle extras = intent.getExtras();
// for (String key : extras.keySet()) {
// Object value = extras.get(key);
// if (!IGNORED_EXTRAS_KEYS.contains(key)) {
// if (key.equals(JPushInterface.EXTRA_NOTIFICATION_ID)) {
// extrasMap.put(key, intent.getIntExtra(key, 0));
// }else if(key.equals("cn.jpush.android.EXTRA")){
// try {
// JSONObject object=new JSONObject((String)value);
// Map<String, Object> useExtra = new HashMap<String, Object>();
// jsonToMap(object,useExtra);
// extrasMap.put(key,useExtra);
// }catch (Throwable throwable){
// }
// } else {
// extrasMap.put(key, value);
// }
// }
// }
// return extrasMap;
// }
// public static void jsonToMap(JSONObject object,Map<String, Object> map) {
// try {
// Iterator<String> keys = object.keys();
// while (keys.hasNext()) {
// String key = keys.next();
// Object value = object.get(key);
// map.put(key, value);
// }
// }catch (Throwable throwable){
// }
// }
// }
}

282
documents/APIs.md Normal file
View File

@ -0,0 +1,282 @@
[Common API](#common-api)
- [addEventHandler](#addeventhandler)
- [setup](#setup)
- [getRegistrationID](#getregistrationid)
- [stopPush](#stoppush)
- [setChannelAndSound](#setChannelAndSound)
- [resumePush](#resumepush)
- [setAlias](#setalias)
- [getAlias](#getAlias)
- [deleteAlias](#deletealias)
- [addTags](#addtags)
- [deleteTags](#deletetags)
- [setTags](#settags)
- [cleanTags](#cleantags)
- [getAllTags](getalltags)
- [sendLocalNotification](#sendlocalnotification)
- [clearAllNotifications](#clearallnotifications)
[iOS Only]()
- [applyPushAuthority](#applypushauthority)
- [setBadge](#setbadge)
- [getLaunchAppNotification](#getlaunchappnotification)
- [pageEnterTo](#pageEnterTo)
- [pageLeave](#pageLeave)
**注意addEventHandler 方法建议放到 setup 之前,其他方法需要在 setup 方法之后调用,**
#### addEventHandler
添加事件监听方法。
```dart
JPush jpush = new JPush();
jpush.addEventHandler(
// 接收通知回调方法。
onReceiveNotification: (Map<String, dynamic> message) async {
print("flutter onReceiveNotification: $message");
},
// 点击通知回调方法。
onOpenNotification: (Map<String, dynamic> message) async {
print("flutter onOpenNotification: $message");
},
// 接收自定义消息回调方法。
onReceiveMessage: (Map<String, dynamic> message) async {
print("flutter onReceiveMessage: $message");
},
onConnected: (Map<String, dynamic> message) async {
print("flutter onConnected: $message");
},
);
```
#### setup
添加初始化方法,调用 setup 方法会执行两个操作:
- 初始化 JPush SDK
- 将缓存的事件下发到 dart 环境中。
**注意:** 插件版本 >= 0.0.8 android 端支持在 setup 方法中动态设置 channel动态设置的 channel 优先级比 manifestPlaceholders 中的 JPUSH_CHANNEL 优先级要高。
```dart
JPush jpush = new JPush();
jpush.setup(
appKey: "替换成你自己的 appKey",
channel: "theChannel",
production: false,
debug: false, // 设置是否打印 debug 日志
);
```
* iOS使用推送功能需要调用申请通知权限的方法详情见 [applyPushAuthority](#applyPushAuthority)。
```
jpush.applyPushAuthority(new NotificationSettingsIOS(
sound: true,
alert: true,
badge: true));
```
#### getRegistrationID
获取 registrationId这个 JPush 运行通过 registrationId 来进行推送.
```dart
JPush jpush = new JPush();
jpush.getRegistrationID().then((rid) { });
```
#### stopPush
停止推送功能,调用该方法将不会接收到通知。
```dart
JPush jpush = new JPush();
jpush.stopPush();
```
#### setChannelAndSound
动态配置 channel 、channel id 及sound优先级比 AndroidManifest 里配置的高
备注channel、channel id为必须参数否则接口调用失败。sound 可选
#### 参数说明
- Object
|参数名称|参数类型|参数说明|
|:-----:|:----:|:-----:|
|channel|string|希望配置的 channel|
|channel_id|string|希望配置的 channel id|
|sound|string|希望配置的 sound(铃声名称只有铃声名称即可如AA.mp3,填写AA )|
#### 示例
```dart
JPush jpush = new JPush();
jpush.setChannelAndSound();
```
#### resumePush
调用 stopPush 后,可以通过 resumePush 方法恢复推送。
```dart
JPush jpush = new JPush();
jpush.resumePush();
```
#### setAlias
设置别名,极光后台可以通过别名来推送,一个 App 应用只有一个别名,一般用来存储用户 id。
```
JPush jpush = new JPush();
jpush.setAlias("your alias").then((map) { });
```
#### deleteAlias
可以通过 deleteAlias 方法来删除已经设置的 alias。
```dart
JPush jpush = new JPush();
jpush.deleteAlias().then((map) {})
```
#### getAlias
获取当前 alias 列表。
```
JPush jpush = new JPush();
jpush.getAlias().then((map) { });
```
#### addTags
在原来的 Tags 列表上添加指定 tags。
```
JPush jpush = new JPush();
jpush.addTags(["tag1","tag2"]).then((map) {});
```
#### deleteTags
在原来的 Tags 列表上删除指定 tags。
```
JPush jpush = new JPush();
jpush.deleteTags(["tag1","tag2"]).then((map) {});
```
#### setTags
重置 tags。
```dart
JPush jpush = new JPush();
jpush.setTags(["tag1","tag2"]).then((map) {});
```
#### cleanTags
清空所有 tags
```dart
jpush.setTags().then((map) {});
```
#### getAllTags
获取当前 tags 列表。
```dart
JPush jpush = new JPush();
jpush.getAllTags().then((map) {});
```
#### sendLocalNotification
指定触发时间,添加本地推送通知。
```dart
// 延时 3 秒后触发本地通知。
JPush jpush = new JPush();
var fireDate = DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch + 3000);
var localNotification = LocalNotification(
id: 234,
title: 'notification title',
buildId: 1,
content: 'notification content',
fireTime: fireDate,
subtitle: 'notification subtitle', // 该参数只有在 iOS 有效
badge: 5, // 该参数只有在 iOS 有效
extras: {"fa": "0"} // 设置 extras extras 需要是 Map<String, String>
);
jpush.sendLocalNotification(localNotification).then((res) {});
```
#### clearAllNotifications
清楚通知栏上所有通知。
```dart
JPush jpush = new JPush();
jpush.clearAllNotifications();
```
#### applyPushAuthority
申请推送权限,注意这个方法只会向用户弹出一次推送权限请求(如果用户不同意,之后只能用户到设置页面里面勾选相应权限),需要开发者选择合适的时机调用。
**注意: iOS10+ 可以通过该方法来设置推送是否前台展示,是否触发声音,是否设置应用角标 badge**
```dart
JPush jpush = new JPush();
jpush.applyPushAuthority(new NotificationSettingsIOS(
sound: true,
alert: true,
badge: true));
```
**iOS Only**
#### setBadge
设置应用 badge 值,该方法还会同步 JPush 服务器的的 badge 值JPush 服务器的 badge 值用于推送 badge 自动 +1 时会用到。
```dart
JPush jpush = new JPush();
jpush.setBadge(66).then((map) {});
```
### getLaunchAppNotification
获取 iOS 点击推送启动应用的那条通知。
```dart
JPush jpush = new JPush();
jpush.getLaunchAppNotification().then((map) {});
```
### pageEnterTo
进入页面应用内消息功能需要配置该接口请与pageLeave函数配套使用
```dart
JPush jpush = new JPush();
jpush.pageEnterTo("页面名");
```
### pageLeave
离开页面应用内消息功能需要配置该接口请与pageEnterTo函数配套使用
```dart
JPush jpush = new JPush();
jpush.pageLeave("页面名");
```

BIN
example/.DS_Store vendored Normal file

Binary file not shown.

8
example/README.md Normal file
View File

@ -0,0 +1,8 @@
# jpush_example
Demonstrates how to use the jpush plugin.
## Getting Started
For help getting started with Flutter, view our online
[documentation](https://flutter.io/).

BIN
example/android/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,96 @@
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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystorePropertiesFile = rootProject.file("key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
compileSdkVersion 31
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
// applicationId "com.jiguang.jpushexample"
applicationId "com.shikk.testJpush" //JPush .
minSdkVersion 17
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
// cpu .so
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
//
}
manifestPlaceholders = [
JPUSH_PKGNAME : applicationId,
JPUSH_APPKEY : "31c7c1b2cf59c1d42895a782", //JPush Appkey.
JPUSH_CHANNEL : "developer-default", //.
]
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
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.release
}
}
// buildToolsVersion '28.0.1'
packagingOptions {
exclude 'lib/arm64-v8a/libgojni.so'
exclude 'lib/x86/libgojni.so'
exclude 'lib/x86_64/libgojni.so'
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

View File

@ -0,0 +1,54 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jiguang.jpushexample">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:label="jpush_example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTask"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</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>

View File

@ -0,0 +1,6 @@
package com.jiguang.jpushexample;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -0,0 +1,31 @@
buildscript {
repositories {
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
}
}
allprojects {
repositories {
mavenCentral()
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -0,0 +1,22 @@
## Project-wide Gradle settings.
#
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Wed Sep 19 16:44:40 CST 2018
#systemProp.http.proxyHost=127.0.0.1
#systemProp.https.proxyPort=1086
org.gradle.jvmargs=-Xmx1536M
#systemProp.https.proxyHost=127.0.0.1
#systemProp.http.proxyPort=1086
android.enableR8=true
android.useAndroidX=true

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Wed Aug 21 15:20:04 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip

160
example/android/gradlew vendored Executable file
View File

@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
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" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

90
example/android/gradlew.bat vendored Normal file
View File

@ -0,0 +1,90 @@
@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
@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=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@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 init
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 init
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
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
: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 %CMD_LINE_ARGS%
: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

View File

@ -0,0 +1,4 @@
storePassword=<password from previous step>
keyPassword=<password from previous step>
keyAlias=key
storeFile=<location of the key store file, e.g. /Users/<user name>/key.jks>

View File

@ -0,0 +1,15 @@
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}

BIN
example/ios/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>

View File

@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

View File

@ -0,0 +1,18 @@
#
# NOTE: This podspec is NOT to be published. It is only used as a local source!
# This is a generated file; do not edit or check into version control.
#
Pod::Spec.new do |s|
s.name = 'Flutter'
s.version = '1.0.0'
s.summary = 'High-performance, high-fidelity mobile apps.'
s.homepage = 'https://flutter.io'
s.license = { :type => 'MIT' }
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
s.ios.deployment_target = '9.0'
# Framework linking is handled by Flutter tooling, not CocoaPods.
# Add a placeholder to satisfy `s.dependency 'Flutter'` plugin podspecs.
s.vendored_frameworks = 'path/to/nothing'
end

View File

@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

View File

@ -0,0 +1,494 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
342565195A7B02408C258C63 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E8558CD656C3CFECC78ECB83 /* libPods-Runner.a */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
243DB7546D048251A9867C1C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
625494FA213F7D30005E4423 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C3EB3B32DF8D367805D86460 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
E8558CD656C3CFECC78ECB83 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
342565195A7B02408C258C63 /* libPods-Runner.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
014620662F76D9C7C4749081 /* Frameworks */ = {
isa = PBXGroup;
children = (
E8558CD656C3CFECC78ECB83 /* libPods-Runner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
AB735DD26662031199114838 /* Pods */,
014620662F76D9C7C4749081 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
625494FA213F7D30005E4423 /* Runner.entitlements */,
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
AB735DD26662031199114838 /* Pods */ = {
isa = PBXGroup;
children = (
243DB7546D048251A9867C1C /* Pods-Runner.debug.xcconfig */,
C3EB3B32DF8D367805D86460 /* Pods-Runner.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
7A418C368FF000006114CEC1 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0910;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = UT282795WK;
ProvisioningStyle = Manual;
SystemCapabilities = {
com.apple.ApplePay = {
enabled = 0;
};
com.apple.BackgroundModes = {
enabled = 1;
};
com.apple.Push = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
};
7A418C368FF000006114CEC1 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UT282795WK;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = cn.jiguang.hxhg;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = cn.jiguang.hxhg;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = UT282795WK;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = cn.jiguang.hxhg;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = cn.jiguang.hxhg;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

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

View File

@ -0,0 +1,6 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end

View File

@ -0,0 +1,14 @@
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#include <jpush_flutter/JPushPlugin.h>
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

View File

@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View File

@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>jpush_example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

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

View File

@ -0,0 +1,9 @@
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}

BIN
example/ios/Runner/sound.caf Executable file

Binary file not shown.

388
example/lib/main.dart Normal file
View File

@ -0,0 +1,388 @@
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:jpush_flutter/jpush_flutter.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? debugLable = 'Unknown';
final JPush jpush = new JPush();
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String? platformVersion;
try {
jpush.addEventHandler(
onReceiveNotification: (Map<String, dynamic> message) async {
print("flutter onReceiveNotification: $message");
setState(() {
debugLable = "flutter onReceiveNotification: $message";
});
}, onOpenNotification: (Map<String, dynamic> message) async {
print("flutter onOpenNotification: $message");
setState(() {
debugLable = "flutter onOpenNotification: $message";
});
}, onReceiveMessage: (Map<String, dynamic> message) async {
print("flutter onReceiveMessage: $message");
setState(() {
debugLable = "flutter onReceiveMessage: $message";
});
}, onReceiveNotificationAuthorization:
(Map<String, dynamic> message) async {
print("flutter onReceiveNotificationAuthorization: $message");
setState(() {
debugLable = "flutter onReceiveNotificationAuthorization: $message";
});
}, onNotifyMessageUnShow: (Map<String, dynamic> message) async {
print("flutter onNotifyMessageUnShow: $message");
setState(() {
debugLable = "flutter onNotifyMessageUnShow: $message";
});
}, onInAppMessageShow: (Map<String, dynamic> message) async {
print("flutter onInAppMessageShow: $message");
setState(() {
debugLable = "flutter onInAppMessageShow: $message";
});
}, onInAppMessageClick: (Map<String, dynamic> message) async {
print("flutter onInAppMessageClick: $message");
setState(() {
debugLable = "flutter onInAppMessageClick: $message";
});
}, onConnected: (Map<String, dynamic> message) async {
print("flutter onConnected: $message");
setState(() {
debugLable = "flutter onConnected: $message";
});
});
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
jpush.setAuth(enable: true);
jpush.setup(
appKey: "xxxxx", // AppKey
channel: "theChannel",
production: false,
debug: true,
);
jpush.applyPushAuthority(
new NotificationSettingsIOS(sound: true, alert: true, badge: true));
// Platform messages may fail, so we use a try/catch PlatformException.
jpush.getRegistrationID().then((rid) {
print("flutter get registration id : $rid");
setState(() {
debugLable = "flutter getRegistrationID: $rid";
});
});
// iOS要是使用应用内消息pageEnterTo pageLeave
jpush.pageEnterTo("HomePage"); // jpush.pageLeave("HomePage");
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
debugLable = platformVersion;
});
}
//
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: const Text('Plugin example app'),
),
body: new Center(
child: new Column(children: [
Container(
margin: EdgeInsets.fromLTRB(10, 10, 10, 10),
color: Colors.brown,
child: Text(debugLable ?? "Unknown"),
width: 350,
height: 100,
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "发本地推送",
onPressed: () {
//
var fireDate = DateTime.fromMillisecondsSinceEpoch(
DateTime.now().millisecondsSinceEpoch + 3000);
var localNotification = LocalNotification(
id: 234,
title: 'fadsfa',
buildId: 1,
content: 'fdas',
fireTime: fireDate,
subtitle: 'fasf',
badge: 5,
extra: {"fa": "0"});
jpush
.sendLocalNotification(localNotification)
.then((res) {
setState(() {
debugLable = res;
});
});
}),
new Text(" "),
new CustomButton(
title: "getLaunchAppNotification",
onPressed: () {
jpush.getLaunchAppNotification().then((map) {
print("flutter getLaunchAppNotification:$map");
setState(() {
debugLable = "getLaunchAppNotification success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "getLaunchAppNotification error: $error";
});
});
}),
]),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "setTags",
onPressed: () {
jpush.setTags(["lala", "haha"]).then((map) {
var tags = map['tags'];
setState(() {
debugLable = "set tags success: $map $tags";
});
}).catchError((error) {
setState(() {
debugLable = "set tags error: $error";
});
});
}),
new Text(" "),
new CustomButton(
title: "addTags",
onPressed: () {
jpush.addTags(["lala", "haha"]).then((map) {
var tags = map['tags'];
setState(() {
debugLable = "addTags success: $map $tags";
});
}).catchError((error) {
setState(() {
debugLable = "addTags error: $error";
});
});
}),
new Text(" "),
new CustomButton(
title: "deleteTags",
onPressed: () {
jpush.deleteTags(["lala", "haha"]).then((map) {
var tags = map['tags'];
setState(() {
debugLable = "deleteTags success: $map $tags";
});
}).catchError((error) {
setState(() {
debugLable = "deleteTags error: $error";
});
});
}),
]),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "getAllTags",
onPressed: () {
jpush.getAllTags().then((map) {
setState(() {
debugLable = "getAllTags success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "getAllTags error: $error";
});
});
}),
new Text(" "),
new CustomButton(
title: "cleanTags",
onPressed: () {
jpush.cleanTags().then((map) {
var tags = map['tags'];
setState(() {
debugLable = "cleanTags success: $map $tags";
});
}).catchError((error) {
setState(() {
debugLable = "cleanTags error: $error";
});
});
}),
]),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "setAlias",
onPressed: () {
jpush.setAlias("thealias11").then((map) {
setState(() {
debugLable = "setAlias success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "setAlias error: $error";
});
});
}),
new Text(" "),
new CustomButton(
title: "deleteAlias",
onPressed: () {
jpush.deleteAlias().then((map) {
setState(() {
debugLable = "deleteAlias success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "deleteAlias error: $error";
});
});
}),
new Text(" "),
new CustomButton(
title: "getAlias",
onPressed: () {
jpush.getAlias().then((map) {
setState(() {
debugLable = "getAlias success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "getAlias error: $error";
});
});
}),
]),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "stopPush",
onPressed: () {
jpush.stopPush();
}),
new Text(" "),
new CustomButton(
title: "resumePush",
onPressed: () {
jpush.resumePush();
}),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "clearAllNotifications",
onPressed: () {
jpush.clearAllNotifications();
}),
new Text(" "),
new CustomButton(
title: "setBadge",
onPressed: () {
jpush.setBadge(66).then((map) {
setState(() {
debugLable = "setBadge success: $map";
});
}).catchError((error) {
setState(() {
debugLable = "setBadge error: $error";
});
});
}),
],
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(" "),
new CustomButton(
title: "通知授权是否打开",
onPressed: () {
jpush.isNotificationEnabled().then((bool value) {
setState(() {
debugLable = "通知授权是否打开: $value";
});
}).catchError((onError) {
setState(() {
debugLable = "通知授权是否打开: ${onError.toString()}";
});
});
}),
new Text(" "),
new CustomButton(
title: "打开系统设置",
onPressed: () {
jpush.openSettingsForNotification();
}),
],
),
])),
),
);
}
}
///
class CustomButton extends StatelessWidget {
final VoidCallback? onPressed;
final String? title;
const CustomButton({@required this.onPressed, @required this.title});
@override
Widget build(BuildContext context) {
return new TextButton(
onPressed: onPressed,
child: new Text("$title"),
style: new ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
overlayColor: MaterialStateProperty.all(Color(0xff888888)),
backgroundColor: MaterialStateProperty.all(Color(0xff585858)),
padding: MaterialStateProperty.all(EdgeInsets.fromLTRB(10, 5, 10, 5)),
),
);
}
}

72
example/pubspec.yaml Normal file
View File

@ -0,0 +1,72 @@
name: jpush_example
description: Demonstrates how to use the jpush plugin.
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# Read more about versioning at semver.org.
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
test: ^1.3.0
mockito: ^3.0.0
flutter_test:
sdk: flutter
jpush_flutter:
path: ../
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, 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 from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages

View File

@ -0,0 +1,54 @@
// This is a basic Flutter widget test.
// To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter
// provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to
// find child widgets in the widget tree, read text, and verify that the values of widget properties
// are correct.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:jpush_example/main.dart';
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:test/test.dart';
void main() {
/*
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(new MyApp());
// Verify that platform version is retrieved.
// expect(
// find.byWidgetPredicate(
// (Widget widget) =>
// widget is Text && widget.data.startsWith('Running on:'),
// ),
// findsOneWidget);
});
MockMethodChannel mockChannel;
JPush.setup(
appKey: "a1703c14b186a68a66ef86c1",
channel: "theChannel",
production: false
);
test('requestNotificationPermissions on ios with custom permissions', () {
JPush.applyPushAuthority(new NotificationSettingsIOS(
sound: false,
alert: false,
badge: false));
// firebaseMessaging.requestNotificationPermissions(
// const IosNotificationSettings(sound: false));
verify(mockChannel.invokeMethod('requestNotificationPermissions',
<String, bool>{'sound': false, 'badge': true, 'alert': true}));
});
*/
}

BIN
ios/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
#import <Flutter/Flutter.h>
@interface JPushPlugin : NSObject<FlutterPlugin>
@property FlutterMethodChannel *channel;
@end

793
ios/Classes/JPushPlugin.m Normal file
View File

@ -0,0 +1,793 @@
#import "JPushPlugin.h"
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif
#import "JPUSHService.h"
#import "JGInforCollectionAuth.h"
#define JPLog(fmt, ...) NSLog((@"| JPUSH | Flutter | iOS | " fmt), ##__VA_ARGS__)
@interface NSError (FlutterError)
@property(readonly, nonatomic) FlutterError *flutterError;
@end
@implementation NSError (FlutterError)
- (FlutterError *)flutterError {
return [FlutterError errorWithCode:[NSString stringWithFormat:@"Error %d", (int)self.code]
message:self.domain
details:self.localizedDescription];
}
@end
#if defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
@interface JPushPlugin ()<JPUSHRegisterDelegate,JPUSHInAppMessageDelegate>
//
@property(assign, nonatomic) BOOL unShow;
@end
#endif
static NSMutableArray<FlutterResult>* getRidResults;
@implementation JPushPlugin {
NSDictionary *_launchNotification;
NSDictionary *_completeLaunchNotification;
BOOL _isJPushDidLogin;
JPAuthorizationOptions notificationTypes;
}
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
getRidResults = @[].mutableCopy;
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"jpush"
binaryMessenger:[registrar messenger]];
JPushPlugin* instance = [[JPushPlugin alloc] init];
instance.channel = channel;
[registrar addApplicationDelegate:instance];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (id)init {
self = [super init];
notificationTypes = 0;
NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter removeObserver:self];
[defaultCenter addObserver:self
selector:@selector(networkConnecting:)
name:kJPFNetworkIsConnectingNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(networkRegister:)
name:kJPFNetworkDidRegisterNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(networkDidSetup:)
name:kJPFNetworkDidSetupNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(networkDidClose:)
name:kJPFNetworkDidCloseNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(networkDidLogin:)
name:kJPFNetworkDidLoginNotification
object:nil];
[defaultCenter addObserver:self
selector:@selector(networkDidReceiveMessage:)
name:kJPFNetworkDidReceiveMessageNotification
object:nil];
return self;
}
- (void)networkConnecting:(NSNotification *)notification {
_isJPushDidLogin = false;
}
- (void)networkRegister:(NSNotification *)notification {
_isJPushDidLogin = false;
}
- (void)networkDidSetup:(NSNotification *)notification {
_isJPushDidLogin = false;
}
- (void)networkDidClose:(NSNotification *)notification {
_isJPushDidLogin = false;
}
- (void)networkDidLogin:(NSNotification *)notification {
_isJPushDidLogin = YES;
for (FlutterResult result in getRidResults) {
result([JPUSHService registrationID]);
}
[getRidResults removeAllObjects];
}
- (void)networkDidReceiveMessage:(NSNotification *)notification {
[_channel invokeMethod:@"onReceiveMessage" arguments: [notification userInfo]];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"handleMethodCall:%@",call.method);
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else if([@"setup" isEqualToString:call.method]) {
[self setup:call result: result];
} else if([@"setUnShowAtTheForeground" isEqualToString:call.method]) {
[self setUnShowAtTheForeground:call result: result];
} else if([@"applyPushAuthority" isEqualToString:call.method]) {
[self applyPushAuthority:call result:result];
} else if([@"setTags" isEqualToString:call.method]) {
[self setTags:call result:result];
} else if([@"cleanTags" isEqualToString:call.method]) {
[self cleanTags:call result:result];
} else if([@"addTags" isEqualToString:call.method]) {
[self addTags:call result:result];
} else if([@"deleteTags" isEqualToString:call.method]) {
[self deleteTags:call result:result];
} else if([@"getAllTags" isEqualToString:call.method]) {
[self getAllTags:call result:result];
} else if([@"setAlias" isEqualToString:call.method]) {
[self setAlias:call result:result];
} else if([@"deleteAlias" isEqualToString:call.method]) {
[self deleteAlias:call result:result];
} else if([@"getAlias" isEqualToString:call.method]) {
[self getAlias:call result:result];
} else if([@"setBadge" isEqualToString:call.method]) {
[self setBadge:call result:result];
} else if([@"stopPush" isEqualToString:call.method]) {
[self stopPush:call result:result];
} else if([@"resumePush" isEqualToString:call.method]) {
[self resumePush:call result:result];
//[self applyPushAuthority:call result:result];
} else if([@"clearAllNotifications" isEqualToString:call.method]) {
[self clearAllNotifications:call result:result];
} else if ([@"clearNotification" isEqualToString:call.method]) {
[self clearNotification:call result:result];
} else if([@"getLaunchAppNotification" isEqualToString:call.method]) {
[self getLaunchAppNotification:call result:result];
} else if([@"getRegistrationID" isEqualToString:call.method]) {
[self getRegistrationID:call result:result];
} else if([@"sendLocalNotification"isEqualToString:call.method]) {
[self sendLocalNotification:call result:result];
} else if([@"isNotificationEnabled"isEqualToString:call.method]) {
[self isNotificationEnabled:call result:result];
} else if([@"openSettingsForNotification"isEqualToString:call.method]) {
[self openSettingsForNotification];
} else if ([@"setAuth" isEqualToString:call.method]) {
[self setAuth:call result:result];
} else if ([@"pageEnterTo" isEqualToString:call.method]) {
[self pageEnterTo:call];
} else if ([@"pageLeave" isEqualToString:call.method]) {
[self pageLeave:call];
} else if ([@"setCollectControl" isEqualToString:call.method]) {
[self setCollectControl:call result:result];
} else{
result(FlutterMethodNotImplemented);
}
}
- (void)setCollectControl:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setCollectControl:%@",call.arguments);
BOOL gps = [call.arguments[@"gps"] boolValue];
JPushCollectControl *control = [[JPushCollectControl alloc] init];
control.gps = gps;
[JPUSHService setCollectControl:control];
}
- (void)setup:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setup:");
NSDictionary *arguments = call.arguments;
NSNumber *debug = arguments[@"debug"];
if ([debug boolValue]) {
[JPUSHService setDebugMode];
} else {
[JPUSHService setLogOFF];
}
[JPUSHService setInAppMessageDelegate:self];
[JPUSHService setupWithOption:_completeLaunchNotification
appKey:arguments[@"appKey"]
channel:arguments[@"channel"]
apsForProduction:[arguments[@"production"] boolValue]];
}
//APP
- (void)setUnShowAtTheForeground:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setUnShowDidEnterBackground:");
NSDictionary *arguments = call.arguments;
NSNumber *unShow = arguments[@"UnShow"];
if(unShow && [unShow isKindOfClass:[NSNumber class]]) self.unShow = [unShow boolValue];
}
- (void)applyPushAuthority:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"applyPushAuthority:%@",call.arguments);
notificationTypes = 0;
NSDictionary *arguments = call.arguments;
if ([arguments[@"sound"] boolValue]) {
notificationTypes |= JPAuthorizationOptionSound;
}
if ([arguments[@"alert"] boolValue]) {
notificationTypes |= JPAuthorizationOptionAlert;
}
if ([arguments[@"badge"] boolValue]) {
notificationTypes |= JPAuthorizationOptionBadge;
}
JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
entity.types = notificationTypes;
[JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
}
- (void)setTags:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setTags:%@",call.arguments);
NSSet *tagSet;
if (call.arguments != NULL) {
tagSet = [NSSet setWithArray: call.arguments];
}
[JPUSHService setTags:tagSet completion:^(NSInteger iResCode, NSSet *iTags, NSInteger seq) {
if (iResCode == 0) {
result(@{@"tags": [iTags allObjects] ?: @[]});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)cleanTags:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"cleanTags:");
[JPUSHService cleanTags:^(NSInteger iResCode, NSSet *iTags, NSInteger seq) {
if (iResCode == 0) {
result(@{@"tags": iTags ? [iTags allObjects] : @[]});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)addTags:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"addTags:%@",call.arguments);
NSSet *tagSet;
if (call.arguments != NULL) {
tagSet = [NSSet setWithArray:call.arguments];
}
[JPUSHService addTags:tagSet completion:^(NSInteger iResCode, NSSet *iTags, NSInteger seq) {
if (iResCode == 0) {
result(@{@"tags": [iTags allObjects] ?: @[]});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)deleteTags:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"deleteTags:%@",call.arguments);
NSSet *tagSet;
if (call.arguments != NULL) {
tagSet = [NSSet setWithArray:call.arguments];
}
[JPUSHService deleteTags:tagSet completion:^(NSInteger iResCode, NSSet *iTags, NSInteger seq) {
if (iResCode == 0) {
result(@{@"tags": [iTags allObjects] ?: @[]});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)getAllTags:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"getAllTags:");
[JPUSHService getAllTags:^(NSInteger iResCode, NSSet *iTags, NSInteger seq) {
if (iResCode == 0) {
result(@{@"tags": iTags ? [iTags allObjects] : @[]});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)setAlias:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setAlias:%@",call.arguments);
NSString *alias = call.arguments;
[JPUSHService setAlias:alias completion:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
if (iResCode == 0) {
result(@{@"alias": iAlias ?: @""});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)deleteAlias:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"deleteAlias:%@",call.arguments);
[JPUSHService deleteAlias:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
if (iResCode == 0) {
result(@{@"alias": iAlias ?: @""});
} else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)getAlias:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"getAlias:%@",call.arguments);
[JPUSHService getAlias:^(NSInteger iResCode, NSString *iAlias, NSInteger seq) {
if (iResCode == 0) {
result(@{@"alias": iAlias ?: @""});
}else {
NSError *error = [[NSError alloc] initWithDomain:@"JPush.Flutter" code:iResCode userInfo:nil];
result([error flutterError]);
}
} seq: 0];
}
- (void)setBadge:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setBadge:%@",call.arguments);
NSInteger badge = [call.arguments[@"badge"] integerValue];
if (badge < 0) {
badge = 0;
}
[[UIApplication sharedApplication] setApplicationIconBadgeNumber: badge];
[JPUSHService setBadge: badge];
}
- (void)stopPush:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"stopPush:");
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
}
- (void)resumePush:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"resumePush:");
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
- (void)clearAllNotifications:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"clearAllNotifications:");
if (@available(iOS 10.0, *)) {
//iOS 10
JPushNotificationIdentifier *identifier = [[JPushNotificationIdentifier alloc] init];
identifier.identifiers = nil;
identifier.delivered = YES; // YES NO
[JPUSHService removeNotification:identifier];
} else {
// iOS 10 iOS 10
[JPUSHService removeNotification:nil];
}
}
- (void)clearNotification:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"clearNotification:");
NSNumber *notificationId = call.arguments;
if (!notificationId) {
return ;
}
JPushNotificationIdentifier *identifier = [[JPushNotificationIdentifier alloc] init];
identifier.identifiers = @[notificationId.stringValue];
if (@available(iOS 10.0, *)) {
//iOS 10 YES NO iOS 10
identifier.delivered = YES;
} else {
// Fallback on earlier versions
}
[JPUSHService removeNotification:identifier];
}
- (void)getLaunchAppNotification:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"getLaunchAppNotification");
result(_launchNotification == nil ? @{}: _launchNotification);
}
- (void)getRegistrationID:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"getRegistrationID:");
#if TARGET_IPHONE_SIMULATOR//
NSLog(@"simulator can not get registrationid");
result(@"");
#elif TARGET_OS_IPHONE//
if ([JPUSHService registrationID] != nil && ![[JPUSHService registrationID] isEqualToString:@""]) {
// registrationID
result([JPUSHService registrationID]);
return;
}
if (_isJPushDidLogin) {//
result(@[[JPUSHService registrationID]]);
} else {
[getRidResults addObject:result];
}
#endif
}
- (void)sendLocalNotification:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"sendLocalNotification:%@",call.arguments);
JPushNotificationContent *content = [[JPushNotificationContent alloc] init];
NSDictionary *params = call.arguments;
if (params[@"title"]) {
content.title = params[@"title"];
}
if (params[@"subtitle"] && ![params[@"subtitle"] isEqualToString:@"<null>"]) {
content.subtitle = params[@"subtitle"];
}
if (params[@"content"]) {
content.body = params[@"content"];
}
if (params[@"badge"]) {
content.badge = params[@"badge"];
}
if (params[@"action"] && ![params[@"action"] isEqualToString:@"<null>"]) {
content.action = params[@"action"];
}
if ([params[@"extra"] isKindOfClass:[NSDictionary class]]) {
content.userInfo = params[@"extra"];
}
if (params[@"soundName"] && ![params[@"soundName"] isEqualToString:@"<null>"]) {
content.sound = params[@"soundName"];
}
if (@available(iOS 15.0, *)) {
content.interruptionLevel = UNNotificationInterruptionLevelActive;
content.relevanceScore = 1;
}
JPushNotificationTrigger *trigger = [[JPushNotificationTrigger alloc] init];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {
if (params[@"fireTime"]) {
NSNumber *date = params[@"fireTime"];
NSTimeInterval currentInterval = [[NSDate date] timeIntervalSince1970];
NSTimeInterval interval = [date doubleValue]/1000 - currentInterval;
interval = interval>0?interval:0;
trigger.timeInterval = interval;
}
}
else {
if (params[@"fireTime"]) {
NSNumber *date = params[@"fireTime"];
trigger.fireDate = [NSDate dateWithTimeIntervalSince1970: [date doubleValue]/1000];
}
}
JPushNotificationRequest *request = [[JPushNotificationRequest alloc] init];
request.content = content;
request.trigger = trigger;
if (params[@"id"]) {
NSNumber *identify = params[@"id"];
request.requestIdentifier = [identify stringValue];
}
request.completionHandler = ^(id result) {
NSLog(@"result");
};
[JPUSHService addNotification:request];
result(@[@[]]);
}
///
- (void)isNotificationEnabled:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"isNotificationEnabled:");
[JPUSHService requestNotificationAuthorization:^(JPAuthorizationStatus status) {
BOOL isEnabled = NO;
if (status == JPAuthorizationStatusAuthorized) {
isEnabled = YES;
}
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:isEnabled],@"isEnabled", nil];
dispatch_async(dispatch_get_main_queue(), ^{
result(dict);
});
}];
}
- (void)openSettingsForNotification {
JPLog(@"openSettingsForNotification:");
[JPUSHService openSettingsForNotification:^(BOOL success) {
JPLog(@"openSettingsForNotification: %@",@(success));
}];
}
- (void)setAuth:(FlutterMethodCall*)call result:(FlutterResult)result {
JPLog(@"setAuth:%@",call.arguments);
BOOL enable = [call.arguments[@"enable"] boolValue];
[JGInforCollectionAuth JCollectionAuth:^(JGInforCollectionAuthItems * _Nonnull authInfo) {
authInfo.isAuth = enable;
}];
}
- (void)pageEnterTo:(FlutterMethodCall*)call {
JPLog(@"pageEnterTo:%@",call.arguments);
NSString *pageName = call.arguments;
[JPUSHService pageEnterTo:pageName];
}
- (void)pageLeave:(FlutterMethodCall*)call {
JPLog(@"pageLeave:%@",call.arguments);
NSString *pageName = call.arguments;
[JPUSHService pageLeave:pageName];
}
- (void)dealloc {
_isJPushDidLogin = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_completeLaunchNotification = launchOptions;
if (launchOptions != nil) {
_launchNotification = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];
_launchNotification = [self jpushFormatAPNSDic:_launchNotification.copy];
}
if ([launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey]) {
UILocalNotification *localNotification = [launchOptions valueForKey:UIApplicationLaunchOptionsLocalNotificationKey];
NSMutableDictionary *localNotificationEvent = @{}.mutableCopy;
localNotificationEvent[@"content"] = localNotification.alertBody;
localNotificationEvent[@"badge"] = @(localNotification.applicationIconBadgeNumber);
localNotificationEvent[@"extras"] = localNotification.userInfo;
localNotificationEvent[@"fireTime"] = [NSNumber numberWithLong:[localNotification.fireDate timeIntervalSince1970] * 1000];
localNotificationEvent[@"soundName"] = [localNotification.soundName isEqualToString:UILocalNotificationDefaultSoundName] ? @"" : localNotification.soundName;
if (@available(iOS 8.2, *)) {
localNotificationEvent[@"title"] = localNotification.alertTitle;
}
_launchNotification = localNotificationEvent;
}
//[self performSelector:@selector(addNotificationWithDateTrigger) withObject:nil afterDelay:2];
return YES;
}
- (void)addNotificationWithDateTrigger {
JPushNotificationTrigger *trigger = [[JPushNotificationTrigger alloc] init];
if (@available(iOS 10.0, *)) {
trigger.timeInterval = 10;
} else {
NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
trigger.fireDate = fireDate;
}
JPushNotificationContent *content = [[JPushNotificationContent alloc] init];
content.title = @"title";
content.subtitle = @"subtitle";
content.body = @"body";
content.badge = @(1);
content.action = @"action";
content.categoryIdentifier = @"categoryIdentifier";
content.threadIdentifier = @"threadIdentifier";
JPushNotificationRequest *request = [[JPushNotificationRequest alloc] init];
request.content = content;
request.trigger = trigger;
request.completionHandler = ^(id result) {
// iOS10resultUNNotificationRequestresultnil
// iOS10resultUILocalNotificationresultnil
if (result) {
NSLog(@"添加日期通知成功 --- %@", result);
}
};
request.requestIdentifier = @"123";
[JPUSHService addNotification:request];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// _resumingFromBackground = YES;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// application.applicationIconBadgeNumber = 1;
// application.applicationIconBadgeNumber = 0;
}
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[JPUSHService registerDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
NSDictionary *settingsDictionary = @{
@"sound" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeSound],
@"badge" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeBadge],
@"alert" : [NSNumber numberWithBool:notificationSettings.types & UIUserNotificationTypeAlert],
};
[_channel invokeMethod:@"onIosSettingsRegistered" arguments:settingsDictionary];
}
- (BOOL)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
JPLog(@"application:didReceiveRemoteNotification:fetchCompletionHandler");
[JPUSHService handleRemoteNotification:userInfo];
if (@available(* ,iOS 10)) {
[_channel invokeMethod:@"onReceiveNotification" arguments:userInfo];
/**
* app,app,onOpenNotification
* didReceiveNotificationResponsedidReceiveRemoteNotification:fetchCompletionHandler:iOSappdidReceiveNotificationResponsedidReceiveRemoteNotification:fetchCompletionHandler:
* didReceiveNotificationResponse onOpenNotificationdidReceiveNotificationResponse:didFinishLaunchflutterjpushdidFinishLaunch
* app
*/
if (_launchNotification && userInfo && [_launchNotification isKindOfClass:[NSDictionary class]] && [userInfo isKindOfClass:[NSDictionary class]]) {
// msgid
NSNumber *launchMsgid = [_launchNotification valueForKey:@"_j_msgid"];
// msgid
NSNumber *msgid = [userInfo valueForKey:@"_j_msgid"];
// id
if ([launchMsgid isKindOfClass:[NSNumber class]] && [msgid isKindOfClass:[NSNumber class]] && [[launchMsgid stringValue] isEqualToString:[msgid stringValue]]) {
[_channel invokeMethod:@"onOpenNotification" arguments:_launchNotification];
}
}
}
completionHandler(UIBackgroundFetchResultNewData);
return YES;
}
// iOS 10
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
JPLog(@"application:didReceiveLocalNotification:");
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSString *title = @"";
if (@available(iOS 8.2, *)) {
title = notification.alertTitle;
} else {
// Fallback on earlier versions
}
NSString *body = notification.alertBody;
NSString *action = notification.alertAction;
[dic setValue:title?:@"" forKey:@"title"];
[dic setValue:body?:@"" forKey:@"body"];
[dic setValue:action?:@"" forKey:@"action"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.channel invokeMethod:@"onOpenNotification" arguments:dic];
});
}
//
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler API_AVAILABLE(ios(10.0)){
JPLog(@"jpushNotificationCenter:willPresentNotification::");
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
if (@available(iOS 10 , *)) {
[_channel invokeMethod:@"onReceiveNotification" arguments: [self jpushFormatAPNSDic:userInfo]];
}
}else{
JPLog(@"iOS10 前台收到本地通知:userInfo%@",userInfo);
}
if (!self.unShow) completionHandler(notificationTypes);
}
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler API_AVAILABLE(ios(10.0)){
JPLog(@"jpushNotificationCenter:didReceiveNotificationResponse::");
NSDictionary * userInfo = response.notification.request.content.userInfo;
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
[JPUSHService handleRemoteNotification:userInfo];
[_channel invokeMethod:@"onOpenNotification" arguments: [self jpushFormatAPNSDic:userInfo]];
}else{
// iOS 10
JPLog(@"iOS10 点击本地通知");
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
NSString *identifier = response.notification.request.identifier;
NSString *body = response.notification.request.content.body;
NSString *categoryIdentifier = response.notification.request.content.categoryIdentifier;
NSString *title = response.notification.request.content.title;
NSString *subtitle = response.notification.request.content.subtitle;
NSString *threadIdentifier = response.notification.request.content.threadIdentifier;
[dic setValue:body?:@"" forKey:@"body"];
[dic setValue:title?:@"" forKey:@"title"];
[dic setValue:subtitle?:@"" forKey:@"subtitle"];
[dic setValue:identifier?:@"" forKey:@"identifier"];
[dic setValue:threadIdentifier?:@"" forKey:@"threadIdentifier"];
[dic setValue:categoryIdentifier?:@"" forKey:@"categoryIdentifier"];
if (userInfo && userInfo.count) {
NSMutableDictionary *extras = [NSMutableDictionary dictionary];
for (NSString *key in userInfo) {
extras[key] = userInfo[key];
}
dic[@"extras"] = extras;
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.channel invokeMethod:@"onOpenNotification" arguments:dic];
});
}
completionHandler();
}
- (void)jpushNotificationAuthorization:(JPAuthorizationStatus)status withInfo:(NSDictionary *)info {
JPLog(@"");
BOOL isEnabled = NO;
if (status == JPAuthorizationStatusAuthorized) {
isEnabled = YES;
}
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:isEnabled],@"isEnabled", nil];
__weak typeof(self) weakself = self;
dispatch_async(dispatch_get_main_queue(), ^{
__strong typeof(self) strongself = weakself;
[strongself.channel invokeMethod:@"onReceiveNotificationAuthorization" arguments: dict];
});
}
- (NSMutableDictionary *)jpushFormatAPNSDic:(NSDictionary *)dic {
NSMutableDictionary *extras = @{}.mutableCopy;
for (NSString *key in dic) {
if([key isEqualToString:@"_j_business"] ||
[key isEqualToString:@"_j_msgid"] ||
[key isEqualToString:@"_j_uid"] ||
[key isEqualToString:@"actionIdentifier"] ||
[key isEqualToString:@"aps"]) {
continue;
}
extras[key] = dic[key];
}
NSMutableDictionary *formatDic = dic.mutableCopy;
formatDic[@"extras"] = extras;
return formatDic;
}
#pragma mark -
- (void)jPushInAppMessageDidShow:(JPushInAppMessage *)inAppMessage {
[_channel invokeMethod:@"onInAppMessageShow" arguments: [self convertInappMsg:inAppMessage]];
}
- (void)jPushInAppMessageDidClick:(JPushInAppMessage *)inAppMessage {
[_channel invokeMethod:@"onInAppMessageClick" arguments: [self convertInappMsg:inAppMessage]];
}
- (NSDictionary *)convertInappMsg:(JPushInAppMessage *)inAppMessage {
NSDictionary *result = @{
@"mesageId": inAppMessage.mesageId ?: @"", // id
@"title": inAppMessage.title ?:@"", //
@"content": inAppMessage.content ?: @"", //
@"target": inAppMessage.target ?: @[], //
@"clickAction": inAppMessage.clickAction ?: @"", //
@"extras": inAppMessage.extras ?: @{} //
};
return result;
}
@end

22
ios/jpush_flutter.podspec Normal file
View File

@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'jpush_flutter'
s.version = '0.0.2'
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 = { 'xudong.rao' => 'xudong.rao@outlook.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'JCore','>= 4.6.2'
s.dependency 'JPush','5.3.0'
s.ios.deployment_target = '8.0'
s.static_framework = true
end

525
lib/jpush_flutter.dart Normal file
View File

@ -0,0 +1,525 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:platform/platform.dart';
typedef Future<dynamic> EventHandler(Map<String, dynamic> event);
class JPush {
static const String flutter_log = "| JPUSH | Flutter | ";
factory JPush() => _instance;
final MethodChannel _channel;
final Platform _platform;
@visibleForTesting
JPush.private(MethodChannel channel, Platform platform)
: _channel = channel,
_platform = platform;
static final JPush _instance =
new JPush.private(const MethodChannel('jpush'), const LocalPlatform());
EventHandler? _onReceiveNotification;
EventHandler? _onOpenNotification;
EventHandler? _onReceiveMessage;
EventHandler? _onReceiveNotificationAuthorization;
EventHandler? _onNotifyMessageUnShow;
EventHandler? _onConnected;
EventHandler? _onInAppMessageClick;
EventHandler? _onInAppMessageShow;
void setup({
String appKey = '',
bool production = false,
String channel = '',
bool debug = false,
}) {
print(flutter_log + "setup:");
_channel.invokeMethod('setup', {
'appKey': appKey,
'channel': channel,
'production': production,
'debug': debug
});
}
void setChannelAndSound({
String channel = '',
String channelID = '',
String sound = '',
}) {
if (_platform.isIOS) {
return;
}
print(flutter_log + "setChannelAndSound:");
_channel.invokeMethod('setChannelAndSound',
{'channel': channel, 'channel_id': channelID, 'sound': sound});
}
//APP活跃在前台时是否展示通知
void setUnShowAtTheForeground({bool unShow = false}) {
print(flutter_log + "setUnShowAtTheForeground:");
_channel.invokeMethod('setUnShowAtTheForeground', {'UnShow': unShow});
}
void setWakeEnable({bool enable = false}) {
_channel.invokeMethod('setWakeEnable', {'enable': enable});
}
void enableAutoWakeup({bool enable = false}) {
if (_platform.isIOS) {
return;
}
_channel.invokeMethod('enableAutoWakeup', {'enable': enable});
}
void setAuth({bool enable = true}) {
print(flutter_log + "setAuth:");
_channel.invokeMethod('setAuth', {'enable': enable});
}
void setLinkMergeEnable({bool enable = true}) {
if (_platform.isIOS) {
return;
}
print(flutter_log + "setLinkMergeEnable:");
_channel.invokeMethod('setLinkMergeEnable', {'enable': enable});
}
void setGeofenceEnable({bool enable = true}) {
if (_platform.isIOS) {
return;
}
print(flutter_log + "setGeofenceEnable:");
_channel.invokeMethod('setGeofenceEnable', {'enable': enable});
}
void setSmartPushEnable({bool enable = true}) {
if (_platform.isIOS) {
return;
}
print(flutter_log + "setSmartPushEnable:");
_channel.invokeMethod('setSmartPushEnable', {'enable': enable});
}
void setCollectControl({
bool imsi = true, // only android
bool mac = true, // only android
bool wifi = true, // only android
bool bssid = true, // only android
bool ssid = true, // only android
bool imei = true, // only android
bool cell = true, // only android
bool gps = true, // only ios
}) {
print(flutter_log + "setCollectControl:");
_channel.invokeMethod('setCollectControl', {
'imsi': imsi,
'mac': mac,
'wifi': wifi,
'bssid': bssid,
'ssid': ssid,
'imei': imei,
'cell': cell,
'gps': gps
});
}
///
/// JPush ()
///
void addEventHandler({
EventHandler? onReceiveNotification,
EventHandler? onOpenNotification,
EventHandler? onReceiveMessage,
EventHandler? onReceiveNotificationAuthorization,
EventHandler? onNotifyMessageUnShow,
EventHandler? onConnected,
EventHandler? onInAppMessageClick,
EventHandler? onInAppMessageShow,
}) {
print(flutter_log + "addEventHandler:");
_onReceiveNotification = onReceiveNotification;
_onOpenNotification = onOpenNotification;
_onReceiveMessage = onReceiveMessage;
_onReceiveNotificationAuthorization = onReceiveNotificationAuthorization;
_onNotifyMessageUnShow = onNotifyMessageUnShow;
_onConnected = onConnected;
_onInAppMessageClick = onInAppMessageClick;
_onInAppMessageShow = onInAppMessageShow;
_channel.setMethodCallHandler(_handleMethod);
}
Future<dynamic> _handleMethod(MethodCall call) async {
print(flutter_log + "_handleMethod:");
switch (call.method) {
case "onReceiveNotification":
return _onReceiveNotification!(call.arguments.cast<String, dynamic>());
case "onOpenNotification":
return _onOpenNotification!(call.arguments.cast<String, dynamic>());
case "onReceiveMessage":
return _onReceiveMessage!(call.arguments.cast<String, dynamic>());
case "onReceiveNotificationAuthorization":
return _onReceiveNotificationAuthorization!(
call.arguments.cast<String, dynamic>());
case "onNotifyMessageUnShow":
return _onNotifyMessageUnShow!(call.arguments.cast<String, dynamic>());
case "onConnected":
return _onConnected!(call.arguments.cast<String, dynamic>());
case "onInAppMessageClick":
return _onInAppMessageClick!(call.arguments.cast<String, dynamic>());
case "onInAppMessageShow":
return _onInAppMessageShow!(call.arguments.cast<String, dynamic>());
default:
throw new UnsupportedError("Unrecognized Event");
}
}
///
/// iOS Only
///
///
void applyPushAuthority(
[NotificationSettingsIOS iosSettings = const NotificationSettingsIOS()]) {
print(flutter_log + "applyPushAuthority:");
if (!_platform.isIOS) {
return;
}
_channel.invokeMethod('applyPushAuthority', iosSettings.toMap());
}
// iOS Only
// pageName pageLeave配套使用
void pageEnterTo(String pageName) {
print(flutter_log + "pageEnterTo:" + pageName);
if (!_platform.isIOS) {
return;
}
_channel.invokeMethod('pageEnterTo', pageName);
}
// iOS Only
// pageName pageEnterTo配套使用
void pageLeave(String pageName) {
print(flutter_log + "pageLeave:" + pageName);
if (!_platform.isIOS) {
return;
}
_channel.invokeMethod('pageLeave', pageName);
}
///
/// Tag tags
///
/// @param {Array} params = [String]
/// @param {Function} success = ({"tags":[String]}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> setTags(List<String> tags) async {
print(flutter_log + "setTags:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('setTags', tags);
return result;
}
///
/// tags
///
/// @param {Function} success = ({"tags":[String]}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> cleanTags() async {
print(flutter_log + "cleanTags:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('cleanTags');
return result;
}
///
/// tags tags
///
/// @param {Array} tags = [String]
/// @param {Function} success = ({"tags":[String]}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> addTags(List<String> tags) async {
print(flutter_log + "addTags:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('addTags', tags);
return result;
}
///
/// tags
///
/// @param {Array} tags = [String]
/// @param {Function} success = ({"tags":[String]}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> deleteTags(List<String> tags) async {
print(flutter_log + "deleteTags:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('deleteTags', tags);
return result;
}
///
/// tags
///
/// @param {Function} success = ({"tags":[String]}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> getAllTags() async {
print(flutter_log + "getAllTags:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('getAllTags');
return result;
}
///
/// alias
///
/// @param {Function} success = ({"alias":String}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> getAlias() async {
print(flutter_log + "getAlias:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('getAlias');
return result;
}
///
/// alias.
///
/// @param {String} alias
///
/// @param {Function} success = ({"alias":String}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> setAlias(String alias) async {
print(flutter_log + "setAlias:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('setAlias', alias);
return result;
}
void testCountryCode(String code) {
print(flutter_log + "testCountryCode:" + code);
_channel.invokeMethod('testCountryCode', code);
}
///
/// alias
///
/// @param {Function} success = ({"alias":String}) => { }
/// @param {Function} fail = ({"errorCode":int}) => { }
///
Future<Map<dynamic, dynamic>> deleteAlias() async {
print(flutter_log + "deleteAlias:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('deleteAlias');
return result;
}
///
/// Badge
///
/// @param {Int} badge
///
/// Android
///
Future setBadge(int badge) async {
print(flutter_log + "setBadge:");
await _channel.invokeMethod('setBadge', {"badge": badge});
}
///
/// resumePush
///
Future stopPush() async {
print(flutter_log + "stopPush:");
await _channel.invokeMethod('stopPush');
}
///
///
///
Future resumePush() async {
print(flutter_log + "resumePush:");
await _channel.invokeMethod('resumePush');
}
///
///
///
Future clearAllNotifications() async {
print(flutter_log + "clearAllNotifications:");
await _channel.invokeMethod('clearAllNotifications');
}
Future clearLocalNotifications() async {
if (_platform.isIOS) {
return;
}
print(flutter_log + "clearLocalNotifications:");
await _channel.invokeMethod('clearLocalNotifications');
}
///
///
/// @param notificationId idLocalNotification id
///
void clearNotification({int notificationId = 0}) {
print(flutter_log + "clearNotification:");
_channel.invokeListMethod("clearNotification", notificationId);
}
///
/// iOS Only
/// notification notification
/// notification remoteNotification localNotification
/// icon notification @{}
/// @param {Function} callback = (Object) => {}
///
Future<Map<dynamic, dynamic>> getLaunchAppNotification() async {
print(flutter_log + "getLaunchAppNotification:");
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('getLaunchAppNotification');
return result;
}
///
/// RegistrationId, JPush RegistrationId
///
/// @param {Function} callback = (String) => {}
///
Future<String> getRegistrationID() async {
print(flutter_log + "getRegistrationID:");
final String rid = await _channel.invokeMethod('getRegistrationID');
return rid;
}
///
///
/// @param {Notification} notification
///
Future<String> sendLocalNotification(LocalNotification notification) async {
print(flutter_log + "sendLocalNotification:");
await _channel.invokeMethod('sendLocalNotification', notification.toMap());
return notification.toMap().toString();
}
/// API
Future<bool> isNotificationEnabled() async {
final Map<dynamic, dynamic> result =
await _channel.invokeMethod('isNotificationEnabled');
bool isEnabled = result["isEnabled"];
return isEnabled;
}
/// API
void openSettingsForNotification() {
_channel.invokeMethod('openSettingsForNotification');
}
void requestRequiredPermission() {
if (_platform.isIOS) {
return;
}
_channel.invokeMethod('requestRequiredPermission');
}
}
class NotificationSettingsIOS {
final bool sound;
final bool alert;
final bool badge;
const NotificationSettingsIOS({
this.sound = true,
this.alert = true,
this.badge = true,
});
Map<String, dynamic> toMap() {
return <String, bool>{'sound': sound, 'alert': alert, 'badge': badge};
}
}
/// @property {number} [buildId] - 1 2 `setStyleCustom`
/// @property {number} [id] - id,
/// @property {string} [title] -
/// @property {string} [content] -
/// @property {object} [extra] - extra
/// @property {number} [fireTime] -
/// // iOS Only
/// @property {number} [badge] -
/// // iOS Only
/// @property {string} [soundName] -
/// // iOS 10+ Only
/// @property {string} [subtitle] -
class LocalNotification {
final int? buildId; //?
final int? id;
final String? title;
final String? content;
final Map<String, String>? extra; //?
final DateTime? fireTime;
final int? badge; //?
final String? soundName; //?
final String? subtitle; //?
const LocalNotification(
{@required this.id,
@required this.title,
@required this.content,
@required this.fireTime,
this.buildId,
this.extra,
this.badge = 0,
this.soundName,
this.subtitle})
: assert(id != null),
assert(title != null),
assert(content != null),
assert(fireTime != null);
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'title': title,
'content': content,
'fireTime': fireTime?.millisecondsSinceEpoch,
'buildId': buildId,
'extra': extra,
'badge': badge,
'soundName': soundName,
'subtitle': subtitle
}..removeWhere((key, value) => value == null);
}
}

61
pubspec.yaml Normal file
View File

@ -0,0 +1,61 @@
name: jpush_flutter
description: JIGUANG officially supported JPush Flutter plugin (Android & iOS). 极光推送官方支持的 Flutter 插件Android & iOS(https://www.jiguang.cn).
version: 2.5.8
# author: xudong.rao <xudong.rao@outlook.com>
homepage: https://www.jiguang.cn
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dependencies:
platform: ^3.0.0
flutter:
sdk: flutter
dev_dependencies:
test: ^1.17.4
mockito: ^5.0.7
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
plugin:
platforms:
android:
package: com.jiguang.jpush
pluginClass: JPushPlugin
ios:
pluginClass: JPushPlugin
# 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.io/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/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.io/custom-fonts/#from-packages