自定义推送ICON

This commit is contained in:
Fin 2021-09-26 16:28:36 +08:00
parent 83ab9ee53c
commit 4fb69a641d
10 changed files with 463 additions and 45 deletions

View File

@ -71,6 +71,9 @@
065BE44B2563D8E1002A8CA4 /* Reusable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE44A2563D8E1002A8CA4 /* Reusable.swift */; };
065BE4502563D939002A8CA4 /* SoundCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */; };
065BE4552565055F002A8CA4 /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 065BE4542565055F002A8CA4 /* HomeViewModel.swift */; };
0660480B2700550600938904 /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0660480A2700550600938904 /* Intents.framework */; };
0660480E2700550600938904 /* IntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0660480D2700550600938904 /* IntentHandler.swift */; };
066048122700550600938904 /* Intent.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 066048092700550600938904 /* Intent.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
0661A543204FDA4100965E4E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0661A542204FDA4100965E4E /* AppDelegate.swift */; };
0661A545204FDA4100965E4E /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0661A544204FDA4100965E4E /* HomeViewController.swift */; };
0661A54A204FDA4100965E4E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0661A549204FDA4100965E4E /* Assets.xcassets */; };
@ -118,6 +121,13 @@
remoteGlobalIDString = 0632CE1D20EC9098003FDF46;
remoteInfo = NotificationContentExtension;
};
066048102700550600938904 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0661A537204FDA4100965E4E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 066048082700550600938904;
remoteInfo = Intent;
};
06CF784521C7A50300A052D7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 0661A537204FDA4100965E4E /* Project object */;
@ -142,6 +152,7 @@
dstSubfolderSpec = 13;
files = (
0632CE2A20EC9098003FDF46 /* NotificationContentExtension.appex in Embed App Extensions */,
066048122700550600938904 /* Intent.appex in Embed App Extensions */,
06CF784721C7A50300A052D7 /* NotificationServiceExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
@ -213,6 +224,10 @@
065BE44A2563D8E1002A8CA4 /* Reusable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Reusable.swift; sourceTree = "<group>"; };
065BE44F2563D939002A8CA4 /* SoundCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoundCellViewModel.swift; sourceTree = "<group>"; };
065BE4542565055F002A8CA4 /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
066048092700550600938904 /* Intent.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Intent.appex; sourceTree = BUILT_PRODUCTS_DIR; };
0660480A2700550600938904 /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; };
0660480D2700550600938904 /* IntentHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentHandler.swift; sourceTree = "<group>"; };
0660480F2700550600938904 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0661A53F204FDA4100965E4E /* Bark.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Bark.app; sourceTree = BUILT_PRODUCTS_DIR; };
0661A542204FDA4100965E4E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0661A544204FDA4100965E4E /* HomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = "<group>"; };
@ -273,6 +288,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
066048062700550600938904 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0660480B2700550600938904 /* Intents.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0661A53C204FDA4100965E4E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -435,6 +458,15 @@
path = Moya;
sourceTree = "<group>";
};
0660480C2700550600938904 /* Intent */ = {
isa = PBXGroup;
children = (
0660480D2700550600938904 /* IntentHandler.swift */,
0660480F2700550600938904 /* Info.plist */,
);
path = Intent;
sourceTree = "<group>";
};
0661A536204FDA4100965E4E = {
isa = PBXGroup;
children = (
@ -447,6 +479,7 @@
0632CE2120EC9098003FDF46 /* NotificationContentExtension */,
06CF784121C7A50300A052D7 /* NotificationServiceExtension */,
06EE1FD126843E9300586708 /* BarkTests */,
0660480C2700550600938904 /* Intent */,
0661A540204FDA4100965E4E /* Products */,
9563D0DB71FE280909AB1C63 /* Pods */,
99BD309BDB7F62B5DC0CECE1 /* Frameworks */,
@ -460,6 +493,7 @@
0632CE1E20EC9098003FDF46 /* NotificationContentExtension.appex */,
06CF784021C7A50300A052D7 /* NotificationServiceExtension.appex */,
06EE1FD026843E9300586708 /* BarkTests.xctest */,
066048092700550600938904 /* Intent.appex */,
);
name = Products;
sourceTree = "<group>";
@ -516,6 +550,7 @@
14F0F73EC45A35FC2482F967 /* Pods_NotificationContentExtension.framework */,
E4EA0C04469BF7B418FF3CB7 /* libPods-Bark.a */,
A24A28EB12CA35B953807C99 /* libPods-NotificationServiceExtension.a */,
0660480A2700550600938904 /* Intents.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -540,6 +575,23 @@
productReference = 0632CE1E20EC9098003FDF46 /* NotificationContentExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
066048082700550600938904 /* Intent */ = {
isa = PBXNativeTarget;
buildConfigurationList = 066048132700550600938904 /* Build configuration list for PBXNativeTarget "Intent" */;
buildPhases = (
066048052700550600938904 /* Sources */,
066048062700550600938904 /* Frameworks */,
066048072700550600938904 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Intent;
productName = Intent;
productReference = 066048092700550600938904 /* Intent.appex */;
productType = "com.apple.product-type.app-extension";
};
0661A53E204FDA4100965E4E /* Bark */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0661A551204FDA4100965E4E /* Build configuration list for PBXNativeTarget "Bark" */;
@ -556,6 +608,7 @@
dependencies = (
0632CE2920EC9098003FDF46 /* PBXTargetDependency */,
06CF784621C7A50300A052D7 /* PBXTargetDependency */,
066048112700550600938904 /* PBXTargetDependency */,
);
name = Bark;
productName = Bark;
@ -604,7 +657,7 @@
0661A537204FDA4100965E4E /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1250;
LastSwiftUpdateCheck = 1300;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = Fin;
TargetAttributes = {
@ -612,6 +665,10 @@
CreatedOnToolsVersion = 9.3;
ProvisioningStyle = Manual;
};
066048082700550600938904 = {
CreatedOnToolsVersion = 13.0;
ProvisioningStyle = Automatic;
};
0661A53E204FDA4100965E4E = {
CreatedOnToolsVersion = 9.2;
ProvisioningStyle = Manual;
@ -650,6 +707,7 @@
0632CE1D20EC9098003FDF46 /* NotificationContentExtension */,
06CF783F21C7A50300A052D7 /* NotificationServiceExtension */,
06EE1FCF26843E9300586708 /* BarkTests */,
066048082700550600938904 /* Intent */,
);
};
/* End PBXProject section */
@ -665,6 +723,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
066048072700550600938904 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
0661A53D204FDA4100965E4E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -799,6 +864,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
066048052700550600938904 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0660480E2700550600938904 /* IntentHandler.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0661A53B204FDA4100965E4E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -883,6 +956,11 @@
target = 0632CE1D20EC9098003FDF46 /* NotificationContentExtension */;
targetProxy = 0632CE2820EC9098003FDF46 /* PBXContainerItemProxy */;
};
066048112700550600938904 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 066048082700550600938904 /* Intent */;
targetProxy = 066048102700550600938904 /* PBXContainerItemProxy */;
};
06CF784621C7A50300A052D7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 06CF783F21C7A50300A052D7 /* NotificationServiceExtension */;
@ -928,7 +1006,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -938,7 +1016,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationContent;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark.NotificationContent";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark.NotificationContent";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
@ -949,7 +1027,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -959,13 +1037,68 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationContent;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark.NotificationContent";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark.NotificationContent";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
066048142700550600938904 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Intent/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Intent;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Fin. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.Intent;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
066048152700550600938904 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Intent/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Intent;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2021 Fin. All rights reserved.";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.Intent;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
0661A54F204FDA4100965E4E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1086,7 +1219,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Bark/Bark.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -1096,7 +1229,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
@ -1109,7 +1242,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Bark/Bark.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -1119,7 +1252,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
@ -1131,7 +1264,7 @@
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/NotificationServiceExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -1143,7 +1276,7 @@
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationServiceExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark.NotificationServiceExtension";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark.NotificationServiceExtension";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1156,7 +1289,7 @@
buildSettings = {
CLANG_ENABLE_OBJC_WEAK = YES;
CODE_SIGN_ENTITLEMENTS = NotificationServiceExtension/NotificationServiceExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 5U8LBRXG3A;
@ -1167,7 +1300,7 @@
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = me.fin.bark.NotificationServiceExtension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.fin.bark.NotificationServiceExtension";
PROVISIONING_PROFILE_SPECIFIER = "match Development me.fin.bark.NotificationServiceExtension";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -1235,6 +1368,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
066048132700550600938904 /* Build configuration list for PBXNativeTarget "Intent" */ = {
isa = XCConfigurationList;
buildConfigurations = (
066048142700550600938904 /* Debug */,
066048152700550600938904 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0661A53A204FDA4100965E4E /* Build configuration list for PBXProject "Bark" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -94,3 +94,6 @@ other = "Other";
faq = "FAQ";
appSC = "App Source Code";
backendSC = "Backend Source Code";
notificationIcon = "Custom Icon";
notificationIconNotice = "Set a custom icon for the push and the set icon will replace the default Bark icon. Icons are automatically cached locally.";

View File

@ -96,3 +96,6 @@ other = "其他";
faq = "常见问题";
appSC = "App源代码";
backendSC = "后端源代码";
notificationIcon = "自定义推送图标";
notificationIconNotice = "为推送设置自定义图标设置的图标将替换默认Bark图标。\图标会自动缓存在本机,相同的图标 URL 仅下载一次。";

View File

@ -55,6 +55,12 @@ class HomeViewModel: ViewModel, ViewModelType {
notice: NSLocalizedString("archiveNotificationMessage"),
queryParameter: "isArchive=1"
),
PreviewModel(
body: NSLocalizedString("notificationIcon"),
notice: NSLocalizedString("notificationIconNotice"),
queryParameter: "icon=https://day.app/assets/images/avatar.jpg",
image: UIImage(named: "icon")
),
PreviewModel(
body: NSLocalizedString("messageGroup"),
notice: NSLocalizedString("groupMessagesNotice"),

22
Intent/Info.plist Normal file
View File

@ -0,0 +1,22 @@
<?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>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsRestrictedWhileLocked</key>
<array/>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.intents-service</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).IntentHandler</string>
</dict>
</dict>
</plist>

125
Intent/IntentHandler.swift Normal file
View File

@ -0,0 +1,125 @@
//
// IntentHandler.swift
// Intent
//
// Created by huangfeng on 2021/9/26.
// Copyright © 2021 Fin. All rights reserved.
//
import Intents
// As an example, this class is set up to handle Message intents.
// You will want to replace this or add other intents as appropriate.
// The intents you wish to handle must be declared in the extension's Info.plist.
// You can test your example integration by saying things to Siri like:
// "Send a message using <myApp>"
// "<myApp> John saying hello"
// "Search for messages in <myApp>"
class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling {
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
// MARK: - INSendMessageIntentHandling
// Implement resolution methods to provide additional information about your intent (optional).
func resolveRecipients(for intent: INSendMessageIntent, with completion: @escaping ([INSendMessageRecipientResolutionResult]) -> Void) {
if let recipients = intent.recipients {
// If no recipients were provided we'll need to prompt for a value.
if recipients.count == 0 {
completion([INSendMessageRecipientResolutionResult.needsValue()])
return
}
var resolutionResults = [INSendMessageRecipientResolutionResult]()
for recipient in recipients {
let matchingContacts = [recipient] // Implement your contact matching logic here to create an array of matching contacts
switch matchingContacts.count {
case 2 ... Int.max:
// We need Siri's help to ask user to pick one from the matches.
resolutionResults += [INSendMessageRecipientResolutionResult.disambiguation(with: matchingContacts)]
case 1:
// We have exactly one matching contact
resolutionResults += [INSendMessageRecipientResolutionResult.success(with: recipient)]
case 0:
// We have no contacts matching the description provided
resolutionResults += [INSendMessageRecipientResolutionResult.unsupported()]
default:
break
}
}
completion(resolutionResults)
} else {
completion([INSendMessageRecipientResolutionResult.needsValue()])
}
}
func resolveContent(for intent: INSendMessageIntent, with completion: @escaping (INStringResolutionResult) -> Void) {
if let text = intent.content, !text.isEmpty {
completion(INStringResolutionResult.success(with: text))
} else {
completion(INStringResolutionResult.needsValue())
}
}
// Once resolution is completed, perform validation on the intent and provide confirmation (optional).
func confirm(intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
// Verify user is authenticated and your app is ready to send a message.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
let response = INSendMessageIntentResponse(code: .ready, userActivity: userActivity)
completion(response)
}
// Handle the completed intent (required).
func handle(intent: INSendMessageIntent, completion: @escaping (INSendMessageIntentResponse) -> Void) {
// Implement your application logic to send a message here.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSendMessageIntent.self))
let response = INSendMessageIntentResponse(code: .success, userActivity: userActivity)
completion(response)
}
// Implement handlers for each intent you wish to handle. As an example for messages, you may wish to also handle searchForMessages and setMessageAttributes.
// MARK: - INSearchForMessagesIntentHandling
func handle(intent: INSearchForMessagesIntent, completion: @escaping (INSearchForMessagesIntentResponse) -> Void) {
// Implement your application logic to find a message that matches the information in the intent.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSearchForMessagesIntent.self))
let response = INSearchForMessagesIntentResponse(code: .success, userActivity: userActivity)
// Initialize with found message's attributes
response.messages = [INMessage(
identifier: "identifier",
content: "I am so excited about SiriKit!",
dateSent: Date(),
sender: INPerson(personHandle: INPersonHandle(value: "sarah@example.com", type: .emailAddress), nameComponents: nil, displayName: "Sarah", image: nil, contactIdentifier: nil, customIdentifier: nil),
recipients: [INPerson(personHandle: INPersonHandle(value: "+1-415-555-5555", type: .phoneNumber), nameComponents: nil, displayName: "John", image: nil, contactIdentifier: nil, customIdentifier: nil)]
)]
completion(response)
}
// MARK: - INSetMessageAttributeIntentHandling
func handle(intent: INSetMessageAttributeIntent, completion: @escaping (INSetMessageAttributeIntentResponse) -> Void) {
// Implement your application logic to set the message attribute here.
let userActivity = NSUserActivity(activityType: NSStringFromClass(INSetMessageAttributeIntent.self))
let response = INSetMessageAttributeIntentResponse(code: .success, userActivity: userActivity)
completion(response)
}
}

View File

@ -22,6 +22,13 @@
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
<dict>
<key>IntentsSupported</key>
<array>
<string>INSendMessageIntent</string>
</array>
</dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.usernotifications.service</string>
<key>NSExtensionPrincipalClass</key>

View File

@ -11,6 +11,7 @@ import UserNotifications
import RealmSwift
import Kingfisher
import MobileCoreServices
import Intents
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
@ -94,17 +95,56 @@ class NotificationService: UNNotificationServiceExtension {
/// - userInfo:
/// - bestAttemptContent: content
/// - complection:
fileprivate func downloadImage(_ userInfo: [AnyHashable : Any], content bestAttemptContent: UNMutableNotificationContent, complection: @escaping () -> () ) {
guard let imageUrl = userInfo["image"] as? String,
let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark"),
let cache = try? ImageCache(name: "shared",cacheDirectoryURL: groupUrl)
fileprivate func downloadImage(_ imageUrl:String, complection: @escaping (_ imageFileUrl:String?) -> () ) {
guard let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark"),
let cache = try? ImageCache(name: "shared",cacheDirectoryURL: groupUrl),
let imageResource = URL(string: imageUrl)
else {
complection(nil)
return
}
func downloadFinished(){
let cacheFileUrl = cache.cachePath(forKey: imageResource.cacheKey)
complection(cacheFileUrl)
}
//
if cache.diskStorage.isCached(forKey: imageResource.cacheKey) {
downloadFinished()
return
}
//
Kingfisher.ImageDownloader.default.downloadImage(with: imageResource, options: nil) { result in
guard let result = try? result.get() else {
complection(nil)
return
}
//
cache.storeToDisk(result.originalData, forKey: imageResource.cacheKey, expiration: StorageExpiration.never) { r in
downloadFinished()
}
}
}
///
/// - Parameters:
/// - userInfo:
/// - bestAttemptContent: content
/// - complection:
fileprivate func setImage(_ userInfo: [AnyHashable : Any], content bestAttemptContent: UNMutableNotificationContent, complection: @escaping () -> () ) {
guard let imageUrl = userInfo["image"] as? String else {
complection()
return
}
func finished(imageFileUrl: String){
func finished(_ imageFileUrl: String?){
guard let imageFileUrl = imageFileUrl else {
complection()
return
}
let copyDestUrl = URL(fileURLWithPath: imageFileUrl).appendingPathExtension(".tmp")
// 使
try? FileManager.default.copyItem(
@ -120,33 +160,78 @@ class NotificationService: UNNotificationServiceExtension {
complection()
}
//
guard let imageResource = URL(string: imageUrl) else {
downloadImage(imageUrl, complection: finished)
}
fileprivate func setIcon(_ userInfo: [AnyHashable : Any], content bestAttemptContent: UNMutableNotificationContent, complection: @escaping () -> () ) {
if #available(iOSApplicationExtension 15.0, *) {
guard let imageUrl = userInfo["icon"] as? String else {
complection()
return
}
func downloadFinished(){
let cacheFileUrl = cache.cachePath(forKey: imageResource.cacheKey)
finished(imageFileUrl: cacheFileUrl)
}
//
if cache.diskStorage.isCached(forKey: imageResource.cacheKey) {
downloadFinished()
return
}
//
Kingfisher.ImageDownloader.default.downloadImage(with: imageResource, options: nil) { result in
guard let result = try? result.get() else {
func finished(_ imageFileUrl: String?){
guard let imageFileUrl = imageFileUrl else {
complection()
return
}
//
cache.storeToDisk(result.originalData, forKey: imageResource.cacheKey, expiration: StorageExpiration.never) { r in
downloadFinished()
var personNameComponents = PersonNameComponents()
personNameComponents.nickname = bestAttemptContent.title
let avatar = INImage(imageData: NSData(contentsOfFile: imageFileUrl)! as Data)
let senderPerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: personNameComponents,
displayName: personNameComponents.nickname,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil,
isMe: false,
suggestionType: .none
)
let mePerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: nil,
displayName: nil,
image: nil,
contactIdentifier: nil,
customIdentifier: nil,
isMe: true,
suggestionType: .none
)
let intent = INSendMessageIntent(
recipients: [mePerson],
outgoingMessageType: .outgoingMessageText,
content: bestAttemptContent.body,
speakableGroupName: INSpeakableString(spokenPhrase: personNameComponents.nickname ?? ""),
conversationIdentifier: "sampleConversationIdentifier",
serviceName: nil,
sender: senderPerson,
attachments: nil
)
intent.setImage(avatar, forParameterNamed: \.sender)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming
interaction.donate(completion: nil)
do {
let content = try self.bestAttemptContent!.updating(from: intent) as! UNMutableNotificationContent
self.bestAttemptContent = content
} catch {
// Handle error
}
complection()
}
downloadImage(imageUrl, complection: finished)
}
else{
complection()
}
}
@ -162,11 +247,15 @@ class NotificationService: UNNotificationServiceExtension {
autoCopy(userInfo, defaultCopy: bestAttemptContent.body)
//
archive(userInfo)
//
downloadImage(userInfo, content: bestAttemptContent) {
contentHandler(bestAttemptContent)
//
setIcon(userInfo, content: self.bestAttemptContent!) {
//
self.setImage(userInfo, content: self.bestAttemptContent!) {
contentHandler(self.bestAttemptContent!)
}
}
}
else{
contentHandler(bestAttemptContent!)
}