提交 b890cc7b authored 作者: 张国庆's avatar 张国庆

Initial commit

上级
.DS_Store
.dart_tool/
.packages
.pub/
build/
.idea/
*.iml
*.lock
\ No newline at end of file
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: bc7bc940836f1f834699625426795fd6f07c18ec
channel: beta
project_type: plugin
example/
.DS_Store
.dart_tool/
.packages
.pub/
build/
.idea/
*.iml
*.lock
\ No newline at end of file
## 2.5.0
* 支持华为角标
## 2.4.0
* SDK版本升级
## 2.3.1
* Merge #46
## 2.3.0
* Android端分离初使化和注册
* 升级Android SDK至3.7.3
## 2.2.0
* Fix #37
## 2.1.0
* Fix #37
## 2.0.0
* Null-Safety
## 1.2.1
* Merge #16
## 1.2.0
* Merge #14
* Merge #15
## 1.1.0
* 支持厂商通道了
## 1.0.3
* Fix #11
## 1.0.2
* Fix #11
## 1.0.1
* 升级kotlin,gradle
* 修复proguard问题
## 1.0.0
* 升级proguard
## 0.0.5
* 升级SDK
* 绑定解绑手机号,仅限Android
## 0.0.4
* use static framework
## 0.0.3
* 修复ios通知栏不显示的问题
## 0.0.2
* reformat code.
## 0.0.1
* initial release.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# Rammus ![pub package](https://img.shields.io/pub/v/rammus.svg)
阿里云推送Flutter插件.
> Rammus这个项目是一位网友*付费*开发的。在此特别感谢这位朋友。
> 能将其开源出来,是要感谢这位朋友的。
> 开源不易,时间有限,可能有很多功能还没有完成,需要大家共同维护,请各位朋友理解。
> 有问题可以提,但请嘴下积德,开源不意味着开源作者欠某些人的。
> 欢迎加入QQ群:892398530共同交流。
欢迎各位使用者PR。
## 麻烦先读一下官方文档
[麻烦读下推送官方文档](https://help.aliyun.com/document_detail/51056.html?spm=a2c4g.11186623.6.623.47bf59abvM9j25)
[Flutter使用Rammus实现阿里云推送](https://my.oschina.net/wupeilin/blog/3108695)
## Android上的配置
### 设置appKey,appSecret
`AndroidManifest.xml`设置appKey,appSecret
```
<meta-data
android:name="com.alibaba.app.appkey"
android:value="" /> <!-- 请填写你自己的- appKey -->
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="" />
```
> 也可以动态设置,具体方式看官方文档
### 初始化SDK
好吧,由于SDK的限制,用户只能在`Application`中的`onCreate`里初始化:
```
RammusPlugin.initPushService(this)
```
此步骤仅进行初始化,**未进行推送渠道的注册**,有关注册渠道的信息请看下方[使用方式](#使用方式)部分。
### 设置第三方推送通道
`AndroidManifest.xml`设置第三方推送的相关信息
```
<!-- 华为 -->
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=华为appid" />
<!-- 小米 -->
<meta-data
android:name="com.xiaomi.push.client.app_id"
android:value=""/>
<meta-data
android:name="com.xiaomi.push.client.app_key"
android:value="" />
<!-- oppo -->
<meta-data
android:name="com.oppo.push.client.app_key"
android:value="" />
<meta-data
android:name="com.oppo.push.client.app_secret"
android:value="" />
<!-- meizu -->
<meta-data
android:name="com.meizu.push.client.app_id"
android:value="" />
<meta-data
android:name="com.meizu.push.client.app_key"
android:value="" />
<!-- vivo -->
<meta-data
android:name="com.vivo.push.app_id"
android:value="" />
<meta-data
android:name="com.vivo.push.api_key"
android:value="" />
<!-- gcm -->
<meta-data
android:name="com.gcm.push.send_id"
android:value="" />
<meta-data
android:name="com.gcm.push.app_id"
android:value="" />
<meta-data
android:name="com.gcm.push.project_id"
android:value="" />
<meta-data
android:name="com.gcm.push.api_key"
android:value="" />
```
在app build.gradle文件中添加第三方推送依赖
```
implementation 'com.aliyun.ams:alicloud-android-third-push-huawei:$version'
implementation 'com.aliyun.ams:alicloud-android-third-push-xiaomi:$version'
implementation 'com.aliyun.ams:alicloud-android-third-push-oppo:$version'
implementation 'com.aliyun.ams:alicloud-android-third-push-vivo:$version'
implementation 'com.aliyun.ams:alicloud-android-third-push-meizu:$version'
implementation 'com.aliyun.ams:alicloud-android-third-push-fcm:$version'
```
> Application在Android原生项目里。不会创建的自行百度。
## iOS上的配置
稍微有点麻烦。
### 添加一下源
在项目中的`PodFile`前面加上下面的两句话
```ruby
source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/aliyun/aliyun-specs.git'
```
### 添加一下info.plist
请参考[这个链接](https://help.aliyun.com/document_detail/30072.html?spm=a2c4g.11186623.6.630.396f40b1t4SLCb)
`info.plist`添加到你的项目中。
到此ios配置完了。
### 关于iOS通知栏
如果你想推送通知的时候在通知栏上有显示请确保调用了下面的代码:
```dart
rammus.configureNotificationPresentationOption();
```
## 使用方式
### 注册推送渠道(Android 端)
> iOS 端目前未将注册渠道与初始化分离,若你的应用目前仅在 iOS 端运行,可以忽略本步骤。
插件提供 `register()` 方法以执行 Android 端 SDK 的 `void register(Context context, CommonCallback callback);`与厂商渠道的 `register` 接口:
```dart
rammus.register();
```
根据需求可以在用户签署隐私政策后再执行本方法,以防止提前获取到用户敏感信息进而影响应用上架应用市场。
更多请见[阿里云文档](https://help.aliyun.com/document_detail/51056.html)
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
group 'com.jarvanmo.rammus'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.6.10'
ext.push_version = '3.8.0'
repositories {
google()
mavenCentral()
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
repositories {
google()
mavenCentral()
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
maven {url 'https://developer.huawei.com/repo/'}
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 32
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 19
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
//主通道依赖
implementation "com.aliyun.ams:alicloud-android-push:$push_version"
//辅助通道依赖
implementation "com.aliyun.ams:alicloud-android-third-push:$push_version"
//厂商通道依赖
implementation "com.aliyun.ams:alicloud-android-third-push-huawei:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-xiaomi:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-oppo:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-vivo:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-honor:$push_version"
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/mo/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
-dontwarn android.databinding.**
-keep class android.databinding.** { *; }
-keepclasseswithmembernames class ** {
native <methods>;
}
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
-keep class com.taobao.** {*;}
-keep class com.alibaba.** {*;}
-keep class com.alipay.** {*;}
-dontwarn com.taobao.**
-dontwarn com.alibaba.**
-dontwarn com.alipay.**
-keep class com.ut.** {*;}
-dontwarn com.ut.**
-keep class com.ta.** {*;}
-dontwarn com.ta.**
-keep class anet.**{*;}
-keep class org.android.spdy.**{*;}
-keep class org.android.agoo.**{*;}
-dontwarn anet.**
-dontwarn org.android.spdy.**
-dontwarn org.android.agoo.**
# 小米通道
-keep class com.xiaomi.** {*;}
-dontwarn com.xiaomi.**
# 华为通道
-keep class com.huawei.** {*;}
-dontwarn com.huawei.**
# GCM/FCM通道
-keep class com.google.firebase.**{*;}
-dontwarn com.google.firebase.**
# OPPO通道
-keep public class * extends android.app.Service
# VIVO通道
-keep class com.vivo.** {*;}
-dontwarn com.vivo.**
# 魅族通道
-keep class com.meizu.cloud.** {*;}
-dontwarn com.meizu.cloud.**
# 荣耀通道
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
\ No newline at end of file
org.gradle.jvmargs=-Xmx1536M
rootProject.name = 'rammus'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jarvanmo.rammus">
<application>
<service android:name=".RammusPushIntentService"
android:exported="false"
>
<intent-filter>
<action android:name="com.alibaba.push2.action.NOTIFICATION_OPENED" />
</intent-filter>
<intent-filter>
<action android:name="com.alibaba.push2.action.NOTIFICATION_REMOVED" />
</intent-filter>
<intent-filter>
<action android:name="com.alibaba.sdk.android.push.RECEIVE" />
</intent-filter>
</service>
</application>
</manifest>
package com.jarvanmo.rammus
import android.os.Bundle
import android.os.Handler
import android.os.PersistableBundle
import android.util.Log
import com.alibaba.sdk.android.push.AndroidPopupActivity
import org.json.JSONObject
class PopupPushActivity: AndroidPopupActivity() {
private val handler = Handler()
override fun onSysNoticeOpened(title: String, summary: String, extras: MutableMap<String, String>) {
Log.d("PopupPushActivity", "onSysNoticeOpened, title: $title, content: $summary, extMap: $extras")
startActivity(packageManager.getLaunchIntentForPackage(packageName))
var jsonExtras = JSONObject()
for (key in extras.keys){
jsonExtras.putOpt(key, extras[key])
}
Log.d("PopupPushActivity", "onSysNoticeOpened extras: ${jsonExtras.toString()}")
handler.postDelayed({RammusPushHandler.methodChannel?.invokeMethod("onNotificationOpened", mapOf(
"title" to title,
"summary" to summary,
"extras" to jsonExtras.toString()
))
finish()
}, 1500)
}
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
}
}
\ No newline at end of file
package com.jarvanmo.rammus
import android.content.pm.ApplicationInfo
import android.os.Bundle
import android.net.Uri
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import android.util.Log
import com.alibaba.sdk.android.push.CommonCallback
import com.alibaba.sdk.android.push.huawei.HuaWeiRegister
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory
import com.alibaba.sdk.android.push.register.*
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar
class RammusPlugin(private val registrar: Registrar, private val methodChannel: MethodChannel) : MethodCallHandler {
companion object {
private const val TAG = "RammusPlugin"
private val inHandler = Handler()
private var gottenApplication : Application? = null
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "com.jarvanmo/rammus")
RammusPushHandler.methodChannel = channel
channel.setMethodCallHandler(RammusPlugin(registrar, channel))
}
@JvmStatic
fun initPushService(application: Application){
gottenApplication = application
PushServiceFactory.init(application.applicationContext)
val pushService = PushServiceFactory.getCloudPushService()
pushService.setPushIntentService(RammusPushIntentService::class.java)
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
when (call.method) {
"register" -> register()
"deviceId" -> result.success(PushServiceFactory.getCloudPushService().deviceId)
"turnOnPushChannel" -> turnOnPushChannel(result)
"turnOffPushChannel" -> turnOffPushChannel(result)
"checkPushChannelStatus" -> checkPushChannelStatus(result)
"bindAccount" -> bindAccount(call, result)
"unbindAccount" -> unbindAccount(result)
"bindTag" -> bindTag(call, result)
"unbindTag" -> unbindTag(call, result)
"listTags" -> listTags(call, result)
"addAlias" -> addAlias(call, result)
"removeAlias" -> removeAlias(call, result)
"listAliases" -> listAliases(result)
"setupNotificationManager" -> setupNotificationManager(call, result)
"bindPhoneNumber" -> bindPhoneNumber(call, result)
"unbindPhoneNumber" -> unbindPhoneNumber(result)
"applicationBadgeNumberClean" ->setApplicationBadgeNumber(call)
else -> result.notImplemented()
}
}
private fun register() {
if (gottenApplication == null) {
Log.w(TAG, "注册推送服务失败,请检查是否在运行本语句前执行了`RammusPlugin.initPushService`.")
return;
}
val pushService = PushServiceFactory.getCloudPushService()
pushService.register(gottenApplication!!.applicationContext, object : CommonCallback {
override fun onSuccess(response: String?) {
inHandler.postDelayed({
RammusPushHandler.methodChannel?.invokeMethod("initCloudChannelResult", mapOf(
"isSuccessful" to true,
"response" to response
))
}, 2000)
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
inHandler.postDelayed({
RammusPushHandler.methodChannel?.invokeMethod("initCloudChannelResult", mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}, 2000)
}
})
val appInfo = gottenApplication!!.packageManager
.getApplicationInfo(gottenApplication!!.packageName, PackageManager.GET_META_DATA)
val xiaomiAppId = appInfo.metaData.getString("com.xiaomi.push.client.app_id")
val xiaomiAppKey = appInfo.metaData.getString("com.xiaomi.push.client.app_key")
if ((xiaomiAppId != null && xiaomiAppId.isNotBlank())
&& (xiaomiAppKey != null && xiaomiAppKey.isNotBlank())){
Log.d(TAG, "正在注册小米推送服务...")
MiPushRegister.register(gottenApplication!!.applicationContext, xiaomiAppId, xiaomiAppKey)
}
val huaweiAppId = appInfo.metaData.getString("com.huawei.hms.client.appid")
if (huaweiAppId != null && huaweiAppId.toString().isNotBlank()){
Log.d(TAG, "正在注册华为推送服务...")
HuaWeiRegister.register(gottenApplication!!)
}
val oppoAppKey = appInfo.metaData.getString("com.oppo.push.client.app_key")
val oppoAppSecret = appInfo.metaData.getString("com.oppo.push.client.app_secret")
if ((oppoAppKey != null && oppoAppKey.isNotBlank())
&& (oppoAppSecret != null && oppoAppSecret.isNotBlank())){
Log.d(TAG, "正在注册Oppo推送服务...")
OppoRegister.register(gottenApplication!!.applicationContext, oppoAppKey, oppoAppSecret)
}
val vivoAppId = appInfo.metaData.getString("com.vivo.push.app_id")
val vivoApiKey = appInfo.metaData.getString("com.vivo.push.api_key")
if ((vivoAppId != null && vivoAppId.isNotBlank())
&& (vivoApiKey != null && vivoApiKey.isNotBlank())){
Log.d(TAG, "正在注册Vivo推送服务...")
VivoRegister.register(gottenApplication!!.applicationContext)
}
}
private fun turnOnPushChannel(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.turnOnPushChannel(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun turnOffPushChannel(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.turnOffPushChannel(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun checkPushChannelStatus(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.checkPushChannelStatus(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun bindAccount(call: MethodCall, result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.bindAccount(call.arguments as String?, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun unbindAccount(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.unbindAccount(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
//bindPhoneNumber
private fun bindPhoneNumber(call: MethodCall, result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.bindPhoneNumber(call.arguments as String?, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun unbindPhoneNumber(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.unbindPhoneNumber(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun bindTag(call: MethodCall, result: Result) {
// target: Int, tags: Array<String>, alias: String, callback: CommonCallback
val target = call.argument("target") ?: 1
val tagsInArrayList = call.argument("tags") ?: arrayListOf<String>()
val alias = call.argument<String?>("alias")
val arr = arrayOfNulls<String>(tagsInArrayList.size)
val tags: Array<String> = tagsInArrayList.toArray(arr)
val pushService = PushServiceFactory.getCloudPushService()
pushService.bindTag(target, tags, alias, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun unbindTag(call: MethodCall, result: Result) {
// target: Int, tags: Array<String>, alias: String, callback: CommonCallback
val target = call.argument("target") ?: 1
val tagsInArrayList = call.argument("tags") ?: arrayListOf<String>()
val alias = call.argument<String?>("alias")
val arr = arrayOfNulls<String>(tagsInArrayList.size)
val tags: Array<String> = tagsInArrayList.toArray(arr)
val pushService = PushServiceFactory.getCloudPushService()
pushService.unbindTag(target, tags, alias, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun listTags(call: MethodCall, result: Result) {
val target = call.arguments as Int? ?: 1
val pushService = PushServiceFactory.getCloudPushService()
pushService.listTags(target, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun addAlias(call: MethodCall, result: Result) {
val alias = call.arguments as String?
val pushService = PushServiceFactory.getCloudPushService()
pushService.addAlias(alias, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun removeAlias(call: MethodCall, result: Result) {
val alias = call.arguments as String?
val pushService = PushServiceFactory.getCloudPushService()
pushService.removeAlias(alias, object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to true,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun listAliases(result: Result) {
val pushService = PushServiceFactory.getCloudPushService()
pushService.listAliases(object : CommonCallback {
override fun onSuccess(response: String?) {
result.success(mapOf(
"isSuccessful" to true,
"response" to response
))
}
override fun onFailed(errorCode: String?, errorMessage: String?) {
result.success(mapOf(
"isSuccessful" to false,
"errorCode" to errorCode,
"errorMessage" to errorMessage
))
}
})
}
private fun setupNotificationManager(call: MethodCall, result: Result) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channels = call.arguments as List<Map<String, Any?>>
val mNotificationManager = registrar.context().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notificationChannels = mutableListOf<NotificationChannel>()
for (channel in channels){
// 通知渠道的id
val id = channel["id"] ?: registrar.context().packageName
// 用户可以看到的通知渠道的名字.
val name = channel["name"] ?: registrar.context().packageName
// 用户可以看到的通知渠道的描述
val description = channel["description"] ?: registrar.context().packageName
val importance = channel["importance"] ?: NotificationManager.IMPORTANCE_DEFAULT
val mChannel = NotificationChannel(id as String, name as String, importance as Int)
// 配置通知渠道的属性
mChannel.description = description as String
mChannel.enableLights(true)
mChannel.enableVibration(true)
notificationChannels.add(mChannel)
}
if (notificationChannels.isNotEmpty()){
mNotificationManager.createNotificationChannels(notificationChannels)
}
}
result.success(true)
}
//设置android角标
private fun setApplicationBadgeNumber(call: MethodCall){
val appInfo = gottenApplication!!.packageManager
.getApplicationInfo(gottenApplication!!.packageName, PackageManager.GET_META_DATA)
var num = call.argument("num") as Int? ?: 0
setHuaWeiApplicationBadgeNumber(num,appInfo)
}
//清理华为角标 https://developer.huawei.com/consumer/cn/doc/development/Corner-Guides/30802
private fun setHuaWeiApplicationBadgeNumber(num: Int,appInfo: ApplicationInfo) {
val huaweiAppId = appInfo.metaData.getString("com.huawei.hms.client.appid")
if (huaweiAppId != null && huaweiAppId.toString().isNotBlank()){
try {
val bundle = Bundle()
bundle.putString("package", registrar.context().packageName) // com.test.badge is your package name
bundle.putString("class", registrar.context().packageName+".MainActivity") // com.test. badge.MainActivity is your apk main activity
bundle.putInt("badgenumber", num)
gottenApplication!!.contentResolver.call(Uri.parse("content://com.huawei.android.launcher.settings/badge/"), "change_badge", null, bundle)
} catch (e: Exception) {
Log.w(TAG, "setHuaWeiApplicationBadgeNumberClean: 失败"+e.message)
}
}
}
}
package com.jarvanmo.rammus
import io.flutter.plugin.common.MethodChannel
/***
* Created by mo on 2019-06-25
* 冷风如刀,以大地为砧板,视众生为鱼肉。
* 万里飞雪,将穹苍作烘炉,熔万物为白银。
**/
internal object RammusPushHandler {
var methodChannel:MethodChannel? = null
}
\ No newline at end of file
package com.jarvanmo.rammus
import android.content.Context
import android.os.Handler
import android.util.Log
import com.alibaba.sdk.android.push.AliyunMessageIntentService
import com.alibaba.sdk.android.push.notification.CPushMessage
/***
* Created by mo on 2019-06-25
* 冷风如刀,以大地为砧板,视众生为鱼肉。
* 万里飞雪,将穹苍作烘炉,熔万物为白银。
**/
class RammusPushIntentService : AliyunMessageIntentService() {
private val handler = Handler()
override fun onNotificationRemoved(context: Context, messageId: String?) {
Log.d("RammusPushIntentService","onNotificationRemoved messageId is $messageId")
handler.postDelayed( {
RammusPushHandler.methodChannel?.invokeMethod("onNotificationRemoved", messageId)
},1500)
}
override fun onNotification(context: Context, title: String?, summary: String?, extras: MutableMap<String, String>?) {
Log.d("RammusPushIntentService","onNotification title is $title, summary is $summary, extras: $extras")
handler.postDelayed({
RammusPushHandler.methodChannel?.invokeMethod("onNotification", mapOf(
"title" to title,
"summary" to summary,
"extras" to extras
))
},1500)
}
override fun onMessage(context: Context, message: CPushMessage) {
Log.d("RammusPushIntentService","onMessage title is ${message.title}, messageId is ${message.messageId}, content is ${message.content}")
handler.postDelayed( {
RammusPushHandler.methodChannel?.invokeMethod("onMessageArrived", mapOf(
"appId" to message.appId,
"content" to message.content,
"messageId" to message.messageId,
"title" to message.title,
"traceInfo" to message.traceInfo
))
},1500)
}
override fun onNotificationOpened(p0: Context?, title: String?, summary: String?, extras: String?) {
Log.d("RammusPushIntentService","onNotificationOpened title is $title, summary is $summary, extras: $extras")
handler.postDelayed({
RammusPushHandler.methodChannel?.invokeMethod("onNotificationOpened", mapOf(
"title" to title,
"summary" to summary,
"extras" to extras
))
},1500)
}
override fun onNotificationReceivedInApp(p0: Context?, title: String?, summary: String?, extras: MutableMap<String, String>?, openType: Int, openActivity: String?, openUrl: String?) {
Log.d("RammusPushIntentService","onNotificationReceivedInApp title is $title, summary is $summary, extras: $extras")
handler.postDelayed( {
RammusPushHandler.methodChannel?.invokeMethod("onNotificationReceivedInApp", mapOf(
"title" to title,
"summary" to summary,
"extras" to extras,
"openType" to openType,
"openActivity" to openActivity,
"openUrl" to openUrl
))
},1500)
}
override fun onNotificationClickedWithNoAction(context: Context, title: String?, summary: String?, extras: String?) {
Log.d("RammusPushIntentService","onNotificationClickedWithNoAction title is $title, summary is $summary, extras: $extras")
handler.postDelayed( {
RammusPushHandler.methodChannel?.invokeMethod("onNotificationClickedWithNoAction", mapOf(
"title" to title,
"summary" to summary,
"extras" to extras
))
}, 1500)
}
}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"rammus","path":"D:\\\\developer\\\\demo\\\\rammus\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"rammus","path":"D:\\\\developer\\\\demo\\\\rammus\\\\","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"rammus","dependencies":[]}],"date_created":"2022-12-14 16:16:48.363165","version":"3.3.9"}
\ No newline at end of file
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
/build/
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: bc7bc940836f1f834699625426795fd6f07c18ec
channel: beta
project_type: app
# rammus_example
Demonstrates how to use the rammus plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 32
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "com.jarvanmo.rammus_example"
minSdkVersion 19
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
//主通道依赖
implementation "com.aliyun.ams:alicloud-android-push:$push_version"
//辅助通道依赖
implementation "com.aliyun.ams:alicloud-android-third-push:$push_version"
//厂商通道依赖
implementation "com.aliyun.ams:alicloud-android-third-push-huawei:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-xiaomi:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-oppo:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-vivo:$push_version"
implementation "com.aliyun.ams:alicloud-android-third-push-honor:$push_version"
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jarvanmo.rammus_example">
<!-- 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"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.jarvanmo.rammus_example">
<!-- 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:name=".MyApplication"
android:label="rammus_example"
tools:replace="android:label"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher">
<meta-data
android:name="com.alibaba.app.appkey"
android:value="" /> <!-- 请填写你自己的- appKey -->
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="" /> <!-- 请填写你自己的appSecret -->
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="" />
<meta-data
android:name="com.xiaomi.push.client.app_id"
android:value=""/>
<meta-data
android:name="com.xiaomi.push.client.app_key"
android:value="" />
<meta-data
android:name="com.oppo.push.client.app_key"
android:value="" />
<meta-data
android:name="com.oppo.push.client.app_secret"
android:value="" />
<meta-data
android:name="com.meizu.push.client.app_id"
android:value="" />
<meta-data
android:name="com.meizu.push.client.app_key"
android:value="" />
<meta-data
android:name="com.vivo.push.app_id"
android:value="" />
<meta-data
android:name="com.vivo.push.api_key"
android:value="" />
<meta-data
android:name="com.gcm.push.send_id"
android:value="" />
<meta-data
android:name="com.gcm.push.app_id"
android:value="" />
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
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.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<!-- Theme to apply as soon as Flutter begins rendering frames -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name="com.jarvanmo.rammus.PopupPushActivity" android:exported="true"/>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
</manifest>
package com.jarvanmo.rammus_example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
package com.jarvanmo.rammus_example
import com.jarvanmo.rammus.RammusPlugin
import io.flutter.app.FlutterApplication
/***
* Created by mo on 2019-06-25
* 冷风如刀,以大地为砧板,视众生为鱼肉。
* 万里飞雪,将穹苍作烘炉,熔万物为白银。
**/
class MyApplication:FlutterApplication() {
override fun onCreate() {
super.onCreate()
RammusPlugin.initPushService(this)
}
}
\ No newline at end of file
<?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>
<?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>
<!-- You can name this style whatever you'd like -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jarvanmo.rammus_example">
<!-- 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"/>
</manifest>
buildscript {
ext.kotlin_version = '1.6.10'
ext.push_version = '3.8.0'
repositories {
google()
mavenCentral()
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
maven {
url 'https://maven.aliyun.com/nexus/content/repositories/releases/'
}
maven {url 'https://developer.huawei.com/repo/'}
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
#Wed Mar 25 13:36:27 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
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
}
0f55108854e2078ef71cea07cdb7a4fa
\ No newline at end of file
<?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>
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#
# 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 = '8.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
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/admin/develop/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/admin/rumms/cat/rammus/example"
export "COCOAPODS_PARALLEL_CODE_SIGN=true"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.dart_tool/package_config.json"
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
source 'https://github.com/CocoaPods/Specs.git'
source 'https://github.com/aliyun/aliyun-specs.git'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
5CA512C263D8280A253C1C82 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 29C70646788488D17FA4DB71 /* libPods-Runner.a */; };
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>"; };
1673817261C4563524C4BFC8 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
29C70646788488D17FA4DB71 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; 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>"; };
8D670128544CDE7AD84B0564 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; 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>"; };
9CECE4072643961A003A4D6F /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
B6FD0B1271144D7B8FC3D135 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CA512C263D8280A253C1C82 /* libPods-Runner.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1B563A88844EAFEE9ED7BAB6 /* Pods */ = {
isa = PBXGroup;
children = (
B6FD0B1271144D7B8FC3D135 /* Pods-Runner.debug.xcconfig */,
1673817261C4563524C4BFC8 /* Pods-Runner.release.xcconfig */,
8D670128544CDE7AD84B0564 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
7E51F83B2CE89A4661AE6EFE /* Frameworks */ = {
isa = PBXGroup;
children = (
29C70646788488D17FA4DB71 /* 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 */,
1B563A88844EAFEE9ED7BAB6 /* Pods */,
7E51F83B2CE89A4661AE6EFE /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
9CECE4072643961A003A4D6F /* 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>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
07F54290D7C0FFE4E3BC813E /* [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;
ProvisioningStyle = Manual;
};
};
};
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 */
07F54290D7C0FFE4E3BC813E /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
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;
};
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";
};
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 */
249021D3217E4FDB00AE95B9 /* Profile */ = {
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 = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
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_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.jarvanmo.rammus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
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_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.jarvanmo.rammus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
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_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.jarvanmo.rammus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
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 */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
<?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"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
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>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
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>
<?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>
<?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>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.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
{
"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"
}
}
{
"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"
}
}
# 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.
\ No newline at end of file
<?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>
<?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>
<?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>rammus_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>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>
<?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>
#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]));
}
}
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:rammus/rammus.dart' as rammus;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String? _platformVersion = 'Unknown';
@override
initState() {
super.initState();
initPlatformState();
if (!Platform.isAndroid) {
rammus.configureNotificationPresentationOption();
}
rammus.initCloudChannelResult.listen((data) {
print(
"----------->init successful ${data.isSuccessful} ${data.errorCode} ${data.errorMessage}");
});
var channels = <rammus.NotificationChannel>[];
channels.add(rammus.NotificationChannel(
"centralized_activity",
"集中活动",
"集中活动",
importance: rammus.AndroidNotificationImportance.MAX,
));
channels.add(rammus.NotificationChannel(
"psychological_tests",
"心理测评",
"心理测评",
importance: rammus.AndroidNotificationImportance.MAX,
));
channels.add(rammus.NotificationChannel(
"system_notice",
"公告信息",
"公告信息",
importance: rammus.AndroidNotificationImportance.MAX,
));
getDeviceId();
rammus.setupNotificationManager(channels);
rammus.onNotification.listen((data) {
print("----------->notification here ${data.summary}");
setState(() {
_platformVersion = data.summary;
});
});
rammus.onNotificationOpened.listen((data) {
print("-----------> ${data.summary} 被点了");
setState(() {
_platformVersion = "${data.summary} 被点了";
});
});
rammus.onNotificationRemoved.listen((data) {
print("-----------> $data 被删除了");
});
rammus.onNotificationReceivedInApp.listen((data) {
print("-----------> ${data.summary} In app");
});
rammus.onNotificationClickedWithNoAction.listen((data) {
print("${data.summary} no action");
});
rammus.onMessageArrived.listen((data) {
print("received data -> ${data.content}");
setState(() {
_platformVersion = data.content;
});
});
// rammus.initCloudChannel( );
}
getDeviceId() async {
var deviceId = await rammus.deviceId;
print("deviceId:::$deviceId");
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
String? platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
// try {
// platformVersion = await Rammus.platformVersion;
// } on PlatformException {
// platformVersion = 'Failed to get platform version.';
// }
// 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(() {
_platformVersion = platformVersion;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Text('Running on: $_platformVersion\n'),
),
),
);
}
}
name: rammus_example
description: Demonstrates how to use the rammus plugin.
publish_to: 'none'
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: ^1.0.3
dev_dependencies:
flutter_test:
sdk: flutter
rammus:
path: ../
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
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.dev/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/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.dev/custom-fonts/#from-packages
// 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:rammus_example/main.dart';
void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());
// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(Widget widget) => widget is Text &&
widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
});
}
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
#import <Flutter/Flutter.h>
#import <UserNotifications/UserNotifications.h>
#import <CloudPushSDK/CloudPushSDK.h>
@interface RammusPlugin : NSObject<FlutterPlugin,UNUserNotificationCenterDelegate>
@end
#import "RammusPlugin.h"
NSString *_isSuccessful = @"isSuccessful";
@implementation RammusPlugin {
// iOS 10通知中心
UNUserNotificationCenter *_notificationCenter;
}
+ (void)registerWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar {
FlutterMethodChannel *channel = [FlutterMethodChannel
methodChannelWithName:@"com.jarvanmo/rammus"
binaryMessenger:[registrar messenger]];
RammusPlugin *instance = [[RammusPlugin alloc] initWithRegistrar:registrar methodChannel:channel];
[registrar addMethodCallDelegate:instance channel:channel];
[registrar addApplicationDelegate:instance];
}
//__weak NSDictionary *_launchOptions;
FlutterMethodChannel *_methodChannel;
UNNotificationPresentationOptions _notificationPresentationOption = UNNotificationPresentationOptionNone;
- (instancetype)initWithRegistrar:(NSObject <FlutterPluginRegistrar> *)registrar methodChannel:(FlutterMethodChannel *)flutterMethodChannel {
self = [super init];
if (self) {
_methodChannel = flutterMethodChannel;
}
return self;
}
- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if ([@"initCloudChannel" isEqualToString:call.method]) {
} else if ([@"deviceId" isEqualToString:call.method]) {
result([CloudPushSDK getDeviceId]);
} else if ([@"bindAccount" isEqualToString:call.method]) {
[self bindAccount:call result:result];
} else if ([@"unbindAccount" isEqualToString:call.method]) {
[self unbindAccount:call result:result];
} else if ([@"bindPhoneNumber" isEqualToString:call.method]) {
[self bindPhoneNumber:call result:result];
} else if ([@"unbindPhoneNumber" isEqualToString:call.method]) {
[self unbindPhoneNumber:call result:result];
} else if ([@"bindTag" isEqualToString:call.method]) {
[self bindTag:call result:result];
} else if ([@"unbindTag" isEqualToString:call.method]) {
[self unbindTag:call result:result];
} else if ([@"listTags" isEqualToString:call.method]) {
[self listTags:call result:result];
} else if ([@"addAlias" isEqualToString:call.method]) {
[self addAlias:call result:result];
} else if ([@"removeAlias" isEqualToString:call.method]) {
[self removeAlias:call result:result];
} else if ([@"listAliases" isEqualToString:call.method]) {
[self listAliases:call result:result];
}else if([@"configureNotificationPresentationOption" isEqualToString:call.method]){
[self configureNotificationPresentationOption:call result:result];
}else if([@"setupNotificationManager" isEqualToString:call.method]){
result(@YES);
}else if([@"badgeClean" isEqualToString:call.method]){
[self badgeClean:call result:result];
}else if([@"applicationBadgeNumberClean" isEqualToString:call.method]){
[self applicationBadgeNumberClean:call result:result];
}else {
result(FlutterMethodNotImplemented);
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// _launchOptions = launchOptions;
[self registerAPNS:application];
[self initCloudPush];
[self listenerOnChannelOpened];
[self registerMessageReceive];
[CloudPushSDK sendNotificationAck:launchOptions];
return NO;
}
#pragma mark APNs Register
/**
* 向APNs注册,获取deviceToken用于推送
*
* @param application
*/
- (void)registerAPNS:(UIApplication *)application {
float systemVersionNum = [[[UIDevice currentDevice] systemVersion] floatValue];
if (systemVersionNum >= 10.0) {
// iOS 10 notifications
_notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
// 创建category,并注册到通知中心
// [self createCustomNotificationCategory];
_notificationCenter.delegate = self;
// 请求推送权限
[_notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError *_Nullable error) {
if (granted) {
// granted
NSLog(@"User authored notification.");
// 向APNs注册,获取deviceToken
dispatch_async(dispatch_get_main_queue(), ^{
[application registerForRemoteNotifications];
});
} else {
// not granted
NSLog(@"User denied notification.");
}
}];
} else if (systemVersionNum >= 8.0) {
// iOS 8 Notifications
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
[application registerUserNotificationSettings:
[UIUserNotificationSettings settingsForTypes:
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
categories:nil]];
[application registerForRemoteNotifications];
#pragma clang diagnostic pop
} else {
// iOS < 8 Notifications
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
#pragma clang diagnostic pop
}
}
/**
* 主动获取设备通知是否授权(iOS 10+)
*/
- (void)getNotificationSettingStatus {
[_notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings *_Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
NSLog(@"User authed.");
} else {
NSLog(@"User denied.");
}
}];
}
/*
* APNs注册成功回调,将返回的deviceToken上传到CloudPush服务器
*/
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSLog(@"Upload deviceToken to CloudPush server.");
[CloudPushSDK registerDevice:deviceToken withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
NSLog(@"Register deviceToken success, deviceToken: %@", [CloudPushSDK getApnsDeviceToken]);
} else {
NSLog(@"Register deviceToken failed, error: %@", res.error);
}
}];
}
/*
* APNs注册失败回调
*/
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"didFailToRegisterForRemoteNotificationsWithError %@", error);
}
#pragma mark SDK Init
- (void)initCloudPush {
// 正式上线建议关闭
[CloudPushSDK turnOnDebug];
// SDK初始化,无需输入配置信息
// 请从控制台下载AliyunEmasServices-Info.plist配置文件,并正确拖入工程
[CloudPushSDK autoInit:^(CloudPushCallbackResult *res) {
if (res.success) {
NSLog(@"Push SDK init success, deviceId: %@.", [CloudPushSDK getDeviceId]);
} else {
NSLog(@"Push SDK init failed, error: %@", res.error);
}
}];
}
#pragma mark Channel Opened
/**
* 注册推送通道打开监听
*/
- (void)listenerOnChannelOpened {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onChannelOpened:)
name:@"CCPDidChannelConnectedSuccess"
object:nil];
}
/**
* 推送通道打开回调
*
* @param notification
*/
- (void)onChannelOpened:(NSNotification *)notification {
}
#pragma mark Receive Message
/**
* @brief 注册推送消息到来监听
*/
- (void)registerMessageReceive {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onMessageReceived:)
name:@"CCPDidReceiveMessageNotification"
object:nil];
}
/**
* 处理到来推送消息
*
* @param notification
*/
- (void)onMessageReceived:(NSNotification *)notification {
CCPSysMessage *message = [notification object];
NSString *title = [[NSString alloc] initWithData:message.title encoding:NSUTF8StringEncoding];
NSString *body = [[NSString alloc] initWithData:message.body encoding:NSUTF8StringEncoding];
// NSLog(@"Receive message title: %@, content: %@.", title, body);
if (![NSThread isMainThread]) {
dispatch_async(dispatch_get_main_queue(), ^{
// if (tempVO.messageContent != nil) {
// [self insertPushMessage:tempVO];
// }
[_methodChannel invokeMethod:@"onMessageArrived" arguments:@{
@"title": title,
@"content": body
}];
});
} else {
[_methodChannel invokeMethod:@"onMessageArrived" arguments:@{
@"title": title,
@"content": body
}];
// if (tempVO.messageContent != nil) {
// [self insertPushMessage:tempVO];
// }
}
}
/**
* 处理iOS 10通知(iOS 10+)
*/
- (void)handleiOS10Notification:(UNNotification *)notification fromFront:(BOOL)fromFront {
UNNotificationRequest *request = notification.request;
UNNotificationContent *content = request.content;
NSDictionary *extras = content.userInfo;
// 通知时间
NSDate *noticeDate = notification.date;
// 标题
NSString *title = content.title;
// 副标题
NSString *subtitle = content.subtitle;
// 内容
NSString *body = content.body;
// 角标
int badge = [content.badge intValue];
// 取得通知自定义字段内容,例:获取key为"Extras"的内容
// NSString *extras = [userInfo valueForKey:@"Extras"];
// 通知角标数清0
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
// 同步角标数到服务端
// [self syncBadgeNum:0];
// 通知打开回执上报
[CloudPushSDK sendNotificationAck:extras];
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSLog(@"Notification, date: %@, title: %@, subtitle: %@, body: %@, badge: %d, extras: %@.", noticeDate, title, subtitle, body, badge, extras);
if (title != nil) {
result[@"title"] = title;
}
if (body != nil) {
result[@"summary"] = body;
}
if (extras != nil) {
result[@"extras"] = [self convertToJsonData:extras];
}
if (subtitle != nil) {
result[@"subtitle"] = subtitle;
}
if (badge != nil) {
result[@"badge"] = @(badge);
}
if (request.identifier != nil) {
result[@"messageId"] = request.identifier;
}
if (fromFront) {
[_methodChannel invokeMethod:@"onNotification" arguments:result];
} else {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[_methodChannel invokeMethod:@"onNotificationOpened" arguments:result];
});
}
}
-(NSString *)convertToJsonData:(NSDictionary *)dict{
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString;
if (!jsonData) {
NSLog(@"%@",error);
}else{
jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
}
NSMutableString *mutStr = [NSMutableString stringWithString:jsonString];
NSRange range = {0,jsonString.length};
//去掉字符串中的空格
[mutStr replaceOccurrencesOfString:@" " withString:@"" options:NSLiteralSearch range:range];
NSRange range2 = {0,mutStr.length};
//去掉字符串中的换行符
[mutStr replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:range2];
return mutStr;
}
/**
* App处于前台时收到通知(iOS 10+)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
NSLog(@"Receive a notification in foregound.");
// 处理iOS 10通知,并上报通知打开回执
[self handleiOS10Notification:notification fromFront:YES];
completionHandler(_notificationPresentationOption);
// 通知不弹出
// completionHandler(UNNotificationPresentationOptionNone);
// 通知弹出,且带有声音、内容和角标
// completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
}
/**
* 触发通知动作时回调,比如点击、删除通知和点击自定义action(iOS 10+)
*/
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
NSString *userAction = response.actionIdentifier;
// 点击通知打开
if ([userAction isEqualToString:UNNotificationDefaultActionIdentifier]) {
// NSLog(@"User opened the notification.");
// 处理iOS 10通知,并上报通知打开回执
[self handleiOS10Notification:response.notification fromFront:NO];
}
// 通知dismiss,category创建时传入UNNotificationCategoryOptionCustomDismissAction才可以触发
if ([userAction isEqualToString:UNNotificationDismissActionIdentifier]) {
[_methodChannel invokeMethod:@"onNotificationRemoved" arguments:response.notification.request.identifier];
// NSLog(@"User dismissed the notification.");
}
NSString *customAction1 = @"action1";
NSString *customAction2 = @"action2";
// 点击用户自定义Action1
if ([userAction isEqualToString:customAction1]) {
NSLog(@"User custom action1.");
}
// 点击用户自定义Action2
if ([userAction isEqualToString:customAction2]) {
NSLog(@"User custom action2.");
}
completionHandler();
}
- (void)bindAccount:(FlutterMethodCall *)call result:(FlutterResult)result {
[CloudPushSDK bindAccount:(NSString *) call.arguments withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)unbindAccount:(FlutterMethodCall *)call result:(FlutterResult)result {
[CloudPushSDK unbindAccount:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)bindPhoneNumber:(FlutterMethodCall *)call result:(FlutterResult)result {
result(@{_isSuccessful: @YES});
// [CloudPushSDK bindAccount:(NSString *) call.arguments withCallback:^(CloudPushCallbackResult *res) {
// if (res.success) {
// if (res.data == nil) {
// result(@{_isSuccessful: @YES});
// } else {
// result(@{_isSuccessful: @YES, @"response": res.data});
//
// };
// } else {
// result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
// }
// }];
}
- (void)unbindPhoneNumber:(FlutterMethodCall *)call result:(FlutterResult)result {
result(@{_isSuccessful: @YES});
// [CloudPushSDK unbindAccount:^(CloudPushCallbackResult *res) {
// if (res.success) {
// if (res.data == nil) {
// result(@{_isSuccessful: @YES});
// } else {
// result(@{_isSuccessful: @YES, @"response": res.data});
//
// };
// } else {
// result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
// }
// }];
}
- (void)bindTag:(FlutterMethodCall *)call result:(FlutterResult)result {
// (title == (id) [NSNull null]) ? nil : title
NSNumber *target = (call.arguments[@"target"] == (id) [NSNull null]) ? @1 : call.arguments[@"target"];
NSString *alias = (call.arguments[@"alias"] == (id) [NSNull null]) ? nil : call.arguments[@"alias"];
[CloudPushSDK bindTag:target.intValue withTags:call.arguments[@"tags"] withAlias:alias withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)unbindTag:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *target = (call.arguments[@"target"] == (id) [NSNull null]) ? @1 : call.arguments[@"target"];
NSString *alias = (call.arguments[@"alias"] == (id) [NSNull null]) ? nil : call.arguments[@"alias"];
[CloudPushSDK unbindTag:target.intValue withTags:call.arguments[@"tags"] withAlias:alias withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)listTags:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *target = (call.arguments == (id) [NSNull null]) ? @1 : call.arguments;
[CloudPushSDK listTags:target.intValue withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)addAlias:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *alias = (call.arguments == (id) [NSNull null]) ? nil : call.arguments;
[CloudPushSDK addAlias:alias withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)removeAlias:(FlutterMethodCall *)call result:(FlutterResult)result {
NSString *alias = (call.arguments == (id) [NSNull null]) ? nil : call.arguments;
[CloudPushSDK removeAlias:alias withCallback:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)listAliases:(FlutterMethodCall *)call result:(FlutterResult)result {
[CloudPushSDK listAliases:^(CloudPushCallbackResult *res) {
if (res.success) {
if (res.data == nil) {
result(@{_isSuccessful: @YES});
} else {
result(@{_isSuccessful: @YES, @"response": res.data});
};
} else {
result(@{_isSuccessful: @NO, @"errorCode": @(res.error.code), @"errorMessage": res.error.domain, @"iosError": [NSString stringWithFormat:@"%@", res.error]});
}
}];
}
- (void)configureNotificationPresentationOption:(FlutterMethodCall *)call result:(FlutterResult)result {
// {"none": none, "sound": sound, "alert": alert, "badge": badge});
BOOL none = [call.arguments[@"none"] boolValue];
if(none){
_notificationPresentationOption = _notificationPresentationOption|UNNotificationPresentationOptionNone;
}
BOOL sound = [call.arguments[@"sound"] boolValue];
if(sound){
_notificationPresentationOption = _notificationPresentationOption |UNNotificationPresentationOptionSound;
}
BOOL alert = [call.arguments[@"alert"] boolValue];
if(alert){
_notificationPresentationOption = _notificationPresentationOption | UNNotificationPresentationOptionAlert;
}
BOOL badge = [call.arguments[@"badge"] boolValue];
if(badge){
_notificationPresentationOption = _notificationPresentationOption | UNNotificationPresentationOptionBadge;
}
result(@YES);
}
- (void)badgeClean:(FlutterMethodCall *)call result:(FlutterResult)result {
int num = [call.arguments[@"num"] intValue];
[CloudPushSDK syncBadgeNum:num withCallback:^(CloudPushCallbackResult *res) {
}];
result(@YES);
}
- (void)applicationBadgeNumberClean:(FlutterMethodCall *)call result:(FlutterResult)result {
int num = [call.arguments[@"num"] intValue];
[UIApplication sharedApplication].applicationIconBadgeNumber = num ;
result(@YES);
}
@end
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'rammus'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin for AliCloud push.'
s.description = <<-DESC
A new Flutter plugin for AliCloud push.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.dependency 'AlicloudPush', '~> 1.9.9'
s.frameworks = ["SystemConfiguration", "CoreTelephony"]
s.libraries = ["z", "sqlite3.0", "resolv"]
s.static_framework = true
s.ios.deployment_target = '8.0'
end
library rammus;
export 'src/cloud_push_message.dart';
export 'src/cloud_push_service_enums.dart';
export 'src/common_callback_result.dart';
export 'src/rammus_iml.dart';
export 'src/cloud_push_service_enums.dart';
\ No newline at end of file
class CloudPushMessage {
final String? messageId;
final String? appId;
final String? title;
final String? content;
final String? traceInfo;
CloudPushMessage(
{this.messageId, this.appId, this.title, this.content, this.traceInfo});
}
class OnNotification {
final String? title;
final String? summary;
final String? extras;
OnNotification(this.title, this.summary, this.extras);
}
class OnNotificationOpened {
final String? title;
final String? summary;
final String? extras;
final String? subtitle;
final int? badge;
OnNotificationOpened(
this.title, this.summary, this.extras, this.subtitle, this.badge);
}
class OnNotificationClickedWithNoAction {
final String? title;
final String? summary;
final Map? extras;
OnNotificationClickedWithNoAction(this.title, this.summary, this.extras);
}
class OnNotificationReceivedInApp {
final String? title;
final String? summary;
final Map? extras;
final int? openType;
final String? openActivity;
final String? openUrl;
OnNotificationReceivedInApp(this.title, this.summary, this.extras,
this.openType, this.openActivity, this.openUrl);
}
enum CloudPushServiceTarget {
// int DEVICE_TARGET = 1;
//int ACCOUNT_TARGET = 2;
//int ALIAS_TARGET = 3;
DEVICE_TARGET,
ACCOUNT_TARGET,
ALIAS_TARGET
}
enum AndroidNotificationImportance { MIN, LOW, DEFAULT, HIGH, MAX }
class CommonCallbackResult {
final bool? isSuccessful;
final String? response;
final String? errorCode;
final String? errorMessage;
final String? iosError;
CommonCallbackResult(
{this.isSuccessful,
this.response,
this.errorCode,
this.errorMessage,
this.iosError});
}
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'cloud_push_message.dart';
import 'cloud_push_service_enums.dart';
import 'common_callback_result.dart';
final MethodChannel _channel = const MethodChannel('com.jarvanmo/rammus')
..setMethodCallHandler(_handler);
StreamController<CommonCallbackResult> _initCloudChannelResultController =
StreamController.broadcast();
///注意可能被多次调用。
///Android SDK文档原话如下:
///如果设备成功注册,将回调callback.onSuccess()方法。
///但如果注册服务器连接失败,则调用callback.onFailed方法,并且自动进行重新注册,直到onSuccess为止。(重试规则会由网络切换等时间自动触发。)
///请在网络通畅的情况下进行相关的初始化调试,如果网络不通,或者App信息配置错误,在onFailed方法中,会有相应的错误码返回,可参考错误处理
Stream<CommonCallbackResult> get initCloudChannelResult =>
_initCloudChannelResultController.stream;
///用于接收服务端推送的消息。
///消息不会弹窗,而是回调该方法。
StreamController<CloudPushMessage> _onMessageArrivedController =
StreamController.broadcast();
Stream<CloudPushMessage> get onMessageArrived =>
_onMessageArrivedController.stream;
///客户端接收到通知后,回调该方法。
///可获取到并处理通知相关的参数。
StreamController<OnNotification> _onNotificationController =
StreamController.broadcast();
Stream<OnNotification> get onNotification => _onNotificationController.stream;
///打开通知时会回调该方法,通知打开上报由SDK自动完成。
StreamController<OnNotificationOpened> _onNotificationOpenedController =
StreamController.broadcast();
Stream<OnNotificationOpened> get onNotificationOpened =>
_onNotificationOpenedController.stream;
///删除通知时回调该方法,通知删除上报由SDK自动完成。
StreamController<String> _onNotificationRemovedController =
StreamController.broadcast();
Stream<String> get onNotificationRemoved =>
_onNotificationRemovedController.stream;
///打开无跳转逻辑(open=4)通知时回调该方法(v2.3.2及以上版本支持),通知打开上报由SDK自动完成。
StreamController<OnNotificationClickedWithNoAction>
_onNotificationClickedWithNoActionController = StreamController.broadcast();
Stream<OnNotificationClickedWithNoAction>
get onNotificationClickedWithNoAction =>
_onNotificationClickedWithNoActionController.stream;
///当用户创建自定义通知样式,并且设置推送应用内到达不创建通知弹窗时调用该回调,且此时不调用onNotification回调(v2.3.3及以上版本支持)
StreamController<OnNotificationReceivedInApp>
_onNotificationReceivedInAppController = StreamController.broadcast();
Stream<OnNotificationReceivedInApp> get onNotificationReceivedInApp =>
_onNotificationReceivedInAppController.stream;
///确保注册成功以后调用获取[deviceId]
Future<String?> get deviceId async {
return _channel.invokeMethod("deviceId");
}
Future<CommonCallbackResult> get pushChannelStatus async {
var result = await _channel.invokeMethod("checkPushChannelStatus");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
);
}
/// 注册设备
/// 仅在 Android 设备生效,且在 Android 端若希望插件正常工作,必须执行一次本方法
/// 分离插件初始化与注册的过程,例如实现在用户同意了隐私政策后再进行远端注册,防止影响应用上架。
void register() {
if (Platform.isAndroid) _channel.invokeMethod("register");
}
// static Future<String> get platformVersion async {
// final String version = await _channel.invokeMethod('getPlatformVersion');
// return version;
// }
///这个返回结果永远都是[true],并不是SDK初始化结果
///初始化结果请监听[initCloudChannelResult]
///只能初始化ios
//Future<bool> initCloudChannel({String appKey, String appSecret}) async {
// return await _channel.invokeMethod(
// "initCloudChannel", {"appKey": appKey, "appSecret": appSecret});
//}
Future<CommonCallbackResult> turnOnPushChannel() async {
var result = await _channel.invokeMethod("turnOnPushChannel");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
);
}
Future<CommonCallbackResult> turnOffPushChannel() async {
var result = await _channel.invokeMethod("turnOffPushChannel");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
);
}
/// Android 文档
///将应用内账号和推送通道相关联,可以实现按账号的定点消息推送;
///设备只能绑定一个账号,同一账号可以绑定到多个设备;
///同一设备更换绑定账号时无需进行解绑,重新调用绑定账号接口即可生效;
///若业务场景需要先解绑后绑定,在解绑账号成功回调中进行绑定绑定操作,以此保证执行的顺序性;
///账户名设置支持64字节。
Future<CommonCallbackResult> bindAccount(String account) async {
assert(account != null);
var result = await _channel.invokeMethod("bindAccount", account);
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
Future<CommonCallbackResult> unbindAccount() async {
var result = await _channel.invokeMethod("unbindAccount");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android only
Future<CommonCallbackResult> bindPhoneNumber(String phoneNumber) async {
var result = await _channel.invokeMethod("bindPhoneNumber", phoneNumber);
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android only
Future<CommonCallbackResult> unbindPhoneNumber() async {
var result = await _channel.invokeMethod("unbindPhoneNumber");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
//void bindTag(int target, String[] tags, String alias, CommonCallback callback);
///Android 文档
///绑定标签到指定目标;
///支持向设备、账号和别名绑定标签,绑定类型由参数target指定;
///绑定标签在10分钟内生效;
///App最多支持绑定1万个标签,单个标签最大支持128字符。
///target 目标类型,1:本设备; 2:本设备绑定账号; 3:别名
///target(V2.3.5及以上版本) 目标类型,CloudPushService.DEVICE_TARGET:本设备; CloudPushService.ACCOUNT_TARGET:本账号; CloudPushService.ALIAS_TARGET:别名
///tags 标签(数组输入)
///alias 别名(仅当target = 3时生效)
///callback 回调
Future<CommonCallbackResult> bindTag(
{@required CloudPushServiceTarget? target,
List<String>? tags,
String? alias}) async {
var result = await _channel.invokeMethod("bindTag", {
"target": target!.index + 1,
"tags": tags ?? <String>[],
"alias": alias
});
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android 文档
///解绑指定目标标签;
///支持解绑设备、账号和别名标签,解绑类型由参数target指定;
///解绑标签在10分钟内生效;
///解绑标签只是解除设备和标签的绑定关系,不等同于删除标签,即该APP下标签仍然存在,系统目前不支持标签的删除。
///target 目标类型,1:本设备; 2:本设备绑定账号; 3:别名
///target(V2.3.5及以上版本) 目标类型,CloudPushService.DEVICE_TARGET:本设备; CloudPushService.ACCOUNT_TARGET:本账号; CloudPushService.ALIAS_TARGET:别名
///tags 标签(数组输入)
///alias 别名(仅当target = 3时生效)
///callback 回调
Future<CommonCallbackResult> unbindTag(
{@required CloudPushServiceTarget? target,
List<String>? tags,
String? alias}) async {
var result = await _channel.invokeMethod("unbindTag", {
"target": target!.index + 1,
"tags": tags ?? <String>[],
"alias": alias
});
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android 文档
///查询目标绑定标签,当前仅支持查询设备标签;
///查询结果可从回调onSuccess(response)的response获取;
///标签绑定成功且生效(10分钟内)后即可查询。
Future<CommonCallbackResult> listTags(CloudPushServiceTarget target) async {
var result = await _channel.invokeMethod("listTags", target.index + 1);
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android 文档
///添加别名
///设备添加别名;
///单个设备最多添加128个别名,且同一别名最多添加到128个设备;
///别名支持128字节。
Future<CommonCallbackResult> addAlias(String alias) async {
var result = await _channel.invokeMethod("addAlias", alias);
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android 文档
///删除别名
///删除设备别名;
///支持删除指定别名和删除全部别名(alias = null || alias.length = 0)。
Future<CommonCallbackResult> removeAlias(String alias) async {
var result = await _channel.invokeMethod("removeAlias", alias);
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
///Android 文档
///查询设备别名;
///查询结果可从回调onSuccess(response)的response中获取;
///从V3.0.9及以上版本开始,接口内部有5s短缓存,5s内多次调用只会请求服务端一次。
Future<CommonCallbackResult> listAliases() async {
var result = await _channel.invokeMethod("listAliases");
return CommonCallbackResult(
isSuccessful: result["isSuccessful"],
response: result["response"],
errorCode: result["errorCode"],
errorMessage: result["errorMessage"],
iosError: result["iosError"]);
}
class NotificationChannel {
const NotificationChannel(this.id, this.name, this.description,
{this.importance = AndroidNotificationImportance.DEFAULT});
final String id;
final String name;
final String description;
final AndroidNotificationImportance importance;
Map<String, dynamic> toJson() {
return {
"id": id,
"name": name,
"description": description,
"importance": importance.index + 1
};
}
}
///这个方法只对android有效
///最好调用这个方法以保证在Android 8以上推送通知好用。
///如果不调用这个方法,请确认你自己创建了NotificationChannel。
///为了更好的用户体验,一些参数请不要用传[null]。
///[id]一定要和后台推送时候设置的通知通道一样,否则Android8.0以上无法完成通知推送。
Future setupNotificationManager(List<NotificationChannel> channels) async {
return _channel.invokeMethod(
"setupNotificationManager", channels.map((e) => e.toJson()).toList());
}
///这个方法仅针对iOS
///设置推送通知显示方式
/// completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
Future configureNotificationPresentationOption(
{bool none: false,
bool sound: true,
bool alert: true,
bool badge: true}) async {
return _channel.invokeMethod("configureNotificationPresentationOption",
{"none": none, "sound": sound, "alert": alert, "badge": badge});
}
///这个方法仅针对iOS
///同步远程角标
Future badgeClean({int num: 0}) async {
if (Platform.isIOS){
return _channel.invokeMethod("badgeClean", {"num": num});
}
}
///清理图标上的角标(包含ios,华为,其他平台需要自行实现)
Future applicationBadgeNumberClean({int num: 0}) async {
return _channel.invokeMethod("applicationBadgeNumberClean", {"num": num});
}
Future<dynamic> _handler(MethodCall methodCall) {
if ("initCloudChannelResult" == methodCall.method) {
_initCloudChannelResultController.add(CommonCallbackResult(
isSuccessful: methodCall.arguments["isSuccessful"],
response: methodCall.arguments["response"],
errorCode: methodCall.arguments["errorCode"],
errorMessage: methodCall.arguments["errorMessage"],
));
} else if ("onMessageArrived" == methodCall.method) {
_onMessageArrivedController.add(CloudPushMessage(
messageId: methodCall.arguments["messageId"],
appId: methodCall.arguments["appId"],
title: methodCall.arguments["title"],
content: methodCall.arguments["content"],
traceInfo: methodCall.arguments["traceInfo"],
));
} else if ("onNotification" == methodCall.method) {
_onNotificationController.add(OnNotification(methodCall.arguments["title"],
methodCall.arguments["summary"], methodCall.arguments["extras"]));
} else if ("onNotificationOpened" == methodCall.method) {
_onNotificationOpenedController.add(OnNotificationOpened(
methodCall.arguments["title"],
methodCall.arguments["summary"],
methodCall.arguments["extras"],
methodCall.arguments["subtitle"],
methodCall.arguments["badge"]));
} else if ("onNotificationRemoved" == methodCall.method) {
_onNotificationRemovedController.add(methodCall.arguments);
} else if ("onNotificationClickedWithNoAction" == methodCall.method) {
_onNotificationClickedWithNoActionController.add(
OnNotificationClickedWithNoAction(methodCall.arguments["title"],
methodCall.arguments["summary"], methodCall.arguments["extras"]));
} else if ("onNotificationReceivedInApp" == methodCall.method) {
_onNotificationReceivedInAppController.add(OnNotificationReceivedInApp(
methodCall.arguments["title"],
methodCall.arguments["summary"],
methodCall.arguments["extras"],
methodCall.arguments["openType"],
methodCall.arguments["openActivity"],
methodCall.arguments["openUrl"]));
}
return Future.value(true);
}
dispose() {
_initCloudChannelResultController.close();
_onMessageArrivedController.close();
_onNotificationController.close();
_onNotificationRemovedController.close();
_onNotificationClickedWithNoActionController.close();
_onNotificationReceivedInAppController.close();
}
name: rammus
description: Flutter plugin for AliCloud push, including both android and ios. Receive background messages and notifications.
version: 2.5.0
homepage: https://github.com/OpenFlutter/rammus
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.12.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# This section identifies this Flutter project as a plugin project.
# The androidPackage and pluginClass identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# adding or updating assets for this project.
plugin:
platforms:
android:
package: com.jarvanmo.rammus
pluginClass: RammusPlugin
ios:
pluginClass: RammusPlugin
# To add assets to your plugin package, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
#
# For details regarding assets in packages, see
# https://flutter.dev/assets-and-images/#from-packages
#
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.
# To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts in packages, see
# https://flutter.dev/custom-fonts/#from-packages
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rammus/rammus.dart';
void main() {
const MethodChannel channel = MethodChannel('rammus');
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('getPlatformVersion', () async {
// expect(await Rammus.platformVersion, '42');
});
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论