mmine 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/mmine +67 -0
- data/lib/mmine.rb +1 -0
- data/lib/mmine/notification_extension_integrator.rb +443 -0
- data/lib/mmine/version.rb +3 -0
- data/resources/MobileMessagingNotificationExtension.entitlements +9 -0
- data/resources/MobileMessagingNotificationServiceExtension.plist +31 -0
- data/resources/NotificationService.swift +25 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2800c10a54597154aa688b4b33c10777331fef21d30c2241a1ec30eb44649242
|
4
|
+
data.tar.gz: eece39c70436d2b8c790a8e6aadc68733959542a162403f48dc63bfd63f68797
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 10cebf9df3bcc9e60c453f349afb2d9293eef2fdf860b927aa19202b9799cf46331f5336d0b396648e34bc248a6d2dca1e84daa16a3274bd11f5b216d58b7419
|
7
|
+
data.tar.gz: 41b64be07b953ee6741133263a9db4cf74230dad4e19baf71777d3a30a0b8e8a6880aacea11c1028a6350e6e8dd24820624fa1f1bab81a3af91be437b8438708
|
data/bin/mmine
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optionparser'
|
4
|
+
require 'mmine'
|
5
|
+
|
6
|
+
first_arg, *the_rest = ARGV
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
integrate_parse = OptionParser.new do |opts|
|
10
|
+
opts.banner = "Usage: mmine [command] [parameters]"
|
11
|
+
opts.on("-p", "--project XCODE_PROJECT", "Path for your Xcode project file (.xcodeproj)") do |project|
|
12
|
+
options[:project] = project
|
13
|
+
end
|
14
|
+
opts.on("-g", "--app-group APP_GROUP_ID", "App Group Id for your shared location. You generate it here firs: https://developer.apple.com/account/ios/identifier/applicationGroup. For more inforamtion see https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19") do |app_group|
|
15
|
+
options[:"app-group"] = app_group
|
16
|
+
end
|
17
|
+
opts.on("-t", "--target MAIN_TARGET", "Name of main Xcode project target") do |target|
|
18
|
+
options[:target] = target
|
19
|
+
end
|
20
|
+
opts.on("-v", "--verbose", "Make verbose logs visible") do |verbose|
|
21
|
+
options[:verbose] = verbose
|
22
|
+
end
|
23
|
+
opts.on("--cordova", "--cordova", "Provide Cordova project specific settings.") do |verbose|
|
24
|
+
options[:cordova] = verbose
|
25
|
+
end
|
26
|
+
opts.on("--swift-version", "--swift-version SWIFT_VER", "Provide Swift Language version for notification extension (by default 4.2)") do |ver|
|
27
|
+
options[:"swift-version"] = ver
|
28
|
+
end
|
29
|
+
opts.on("-h", "--help", "Prints this help") do
|
30
|
+
puts opts
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
case first_arg
|
36
|
+
when "integrate"
|
37
|
+
begin
|
38
|
+
integrate_parse.parse!
|
39
|
+
mandatory = [:"project", :"app-group", :"target"]
|
40
|
+
missing = mandatory.select{ |param| options[param].nil? }
|
41
|
+
unless missing.empty?
|
42
|
+
raise OptionParser::MissingArgument.new(missing.join(', '))
|
43
|
+
end
|
44
|
+
integrator = NotificationExtensionIntegrator.new(options[:project], options[:"app-group"], options[:target], options[:cordova] || false, options[:"swift-version"] || "4.2")
|
45
|
+
integrator.logger = Logger.new(STDOUT)
|
46
|
+
integrator.logger.formatter = proc do |severity, datetime, progname, msg|
|
47
|
+
"#{severity}: #{msg}\n"
|
48
|
+
end
|
49
|
+
if options[:verbose]
|
50
|
+
integrator.logger.level = Logger::DEBUG
|
51
|
+
else
|
52
|
+
integrator.logger.level = Logger::WARN
|
53
|
+
end
|
54
|
+
integrator.setupNotificationExtension()
|
55
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
56
|
+
puts $!.to_s
|
57
|
+
puts integrate_parse
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
else
|
61
|
+
if first_arg == nil
|
62
|
+
puts "Please specify a command. For example 'mmine integrate'"
|
63
|
+
else
|
64
|
+
puts "Unknown command: #{first_arg}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
data/lib/mmine.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'mmine/notification_extension_integrator'
|
@@ -0,0 +1,443 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'logger'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
module Mmine
|
9
|
+
def self.root
|
10
|
+
File.expand_path '../..', File.dirname(__FILE__)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NotificationExtensionIntegrator
|
15
|
+
def initialize(project_file_path, app_group, main_target_name, cordova = false, swift_ver)
|
16
|
+
@project_file_path = project_file_path
|
17
|
+
@app_group = app_group
|
18
|
+
@main_target_name = main_target_name
|
19
|
+
@logger = nil
|
20
|
+
@cordova = cordova
|
21
|
+
@swift_version = swift_ver
|
22
|
+
|
23
|
+
@project_dir = Pathname.new(@project_file_path).parent.to_s
|
24
|
+
@project = Xcodeproj::Project.open(@project_file_path)
|
25
|
+
@ne_target_name = 'MobileMessagingNotificationExtension'
|
26
|
+
@extension_source_name_filepath = File.join(Mmine.root, 'resources','NotificationService.swift')
|
27
|
+
@extension_dir_name = 'NotificationExtension'
|
28
|
+
@extension_destination_dir = File.join(@project_dir, @extension_dir_name)
|
29
|
+
@extension_code_destination_filepath = File.join(@extension_destination_dir, 'NotificationService.swift')
|
30
|
+
@extension_group_name = 'NotificationExtensionGroup'
|
31
|
+
|
32
|
+
@plist_name = 'MobileMessagingNotificationServiceExtension.plist'
|
33
|
+
@plist_source_filepath = File.join(Mmine.root, 'resources', @plist_name)
|
34
|
+
@extension_info_plist_path = File.join(@project_dir, @extension_dir_name, @plist_name)
|
35
|
+
|
36
|
+
@main_target = @project.native_targets().select { |target| target.name == @main_target_name }.first
|
37
|
+
@main_target_build_settings_debug = @main_target.build_configurations.select { |config| config.type == :debug }.first.build_settings
|
38
|
+
@main_target_build_settings_release = @main_target.build_configurations.select { |config| config.type == :release }.first.build_settings
|
39
|
+
@main_target_debug_plist = resolveAbsolutePath(@main_target_build_settings_debug["INFOPLIST_FILE"])
|
40
|
+
@main_target_release_plist = resolveAbsolutePath(@main_target_build_settings_release["INFOPLIST_FILE"])
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger=(_logger)
|
44
|
+
@logger = _logger
|
45
|
+
end
|
46
|
+
def logger
|
47
|
+
return @logger
|
48
|
+
end
|
49
|
+
|
50
|
+
def setupNotificationExtension
|
51
|
+
|
52
|
+
createNotificationExtensionTarget()
|
53
|
+
createNotificationExtensionDir()
|
54
|
+
addNotificationExtensionSourceCode()
|
55
|
+
setupDevelopmentTeam()
|
56
|
+
setupDeploymentTarget()
|
57
|
+
setupNotificationExtensionInfoPlist()
|
58
|
+
setupNotificationExtensionBundleId()
|
59
|
+
setupNotificationExtensionEntitlements()
|
60
|
+
setupMainTargetEntitlements()
|
61
|
+
setupAppGroupPlistValue()
|
62
|
+
setupBackgroundModesPlistValue()
|
63
|
+
setupExtensionTargetCapabilities()
|
64
|
+
setupMainTargetCapabilities()
|
65
|
+
setupEmbedExtensionAction()
|
66
|
+
setupMainTargetDependency()
|
67
|
+
setupSwiftVersion()
|
68
|
+
setupProductName()
|
69
|
+
|
70
|
+
if @cordova
|
71
|
+
setupFrameworkSearchPaths()
|
72
|
+
setupRunpathSearchPaths()
|
73
|
+
setupLibCordovaLink()
|
74
|
+
setupCopyFrameworkScript()
|
75
|
+
end
|
76
|
+
|
77
|
+
@project.save()
|
78
|
+
puts "🏁 Integration has been finished successfully!"
|
79
|
+
end
|
80
|
+
|
81
|
+
def createNotificationExtensionTarget
|
82
|
+
@ne_target = @project.native_targets().select { |target| target.name == @ne_target_name }.first
|
83
|
+
if @ne_target == nil
|
84
|
+
@logger.info("Creating notification extension target with name #{@ne_target_name}")
|
85
|
+
@ne_target = @project.new_target(:app_extension, @ne_target_name, ':ios')
|
86
|
+
else
|
87
|
+
@logger.info("Notification extension target already exists, reusing...")
|
88
|
+
end
|
89
|
+
|
90
|
+
@extension_build_settings_debug = @ne_target.build_configurations.select { |config| config.name == 'Debug' }.first.build_settings
|
91
|
+
@extension_build_settings_release = @ne_target.build_configurations.select { |config| config.name == 'Release' }.first.build_settings
|
92
|
+
|
93
|
+
@ne_target.frameworks_build_phase.files_references.each { |ref|
|
94
|
+
@ne_target.frameworks_build_phase.remove_file_reference(ref)
|
95
|
+
}
|
96
|
+
|
97
|
+
@logger.info("Notification extension target debug build settings:\n#{JSON.pretty_generate(@extension_build_settings_debug)}")
|
98
|
+
@logger.info("Notification extension target release build settings:\n#{JSON.pretty_generate(@extension_build_settings_release)}")
|
99
|
+
end
|
100
|
+
|
101
|
+
def createNotificationExtensionDir
|
102
|
+
unless File.directory?(@extension_destination_dir)
|
103
|
+
@logger.info("Creating directory: #{@extension_destination_dir}")
|
104
|
+
FileUtils.mkdir_p(@extension_destination_dir)
|
105
|
+
else
|
106
|
+
@logger.info("Notification extension directory already exists: #{@extension_destination_dir}")
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def addNotificationExtensionSourceCode
|
111
|
+
unless File.exist?(@extension_code_destination_filepath)
|
112
|
+
@logger.info("Copying notification extension source code to path: #{@extension_code_destination_filepath}")
|
113
|
+
FileUtils.cp(@extension_source_name_filepath, @extension_code_destination_filepath)
|
114
|
+
filereference = getNotificationExtensionGroupReference().new_reference(@extension_code_destination_filepath)
|
115
|
+
@ne_target.add_file_references([filereference])
|
116
|
+
else
|
117
|
+
@logger.info("Notification extension source code already exists on path: #{@extension_code_destination_filepath}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def setupDevelopmentTeam
|
122
|
+
setNotificationExtensionBuildSettings('DEVELOPMENT_TEAM', @main_target_build_settings_debug['DEVELOPMENT_TEAM'], @main_target_build_settings_release['DEVELOPMENT_TEAM'])
|
123
|
+
end
|
124
|
+
|
125
|
+
def setupDeploymentTarget
|
126
|
+
setNotificationExtensionBuildSettings('IPHONEOS_DEPLOYMENT_TARGET', "10.0")
|
127
|
+
end
|
128
|
+
|
129
|
+
def setupNotificationExtensionInfoPlist
|
130
|
+
unless File.exist?(@extension_info_plist_path)
|
131
|
+
@logger.info("Copying extension plist file to path: #{@extension_info_plist_path}")
|
132
|
+
FileUtils.cp(@plist_source_filepath, @extension_info_plist_path)
|
133
|
+
getNotificationExtensionGroupReference().new_reference(@extension_info_plist_path) #check if additional plist manipulations needed (target membership?)
|
134
|
+
else
|
135
|
+
@logger.info("Notification extension info plist already exists on path: #{@extension_info_plist_path}")
|
136
|
+
end
|
137
|
+
setNotificationExtensionBuildSettings('INFOPLIST_FILE', resolveXcodePath(@extension_info_plist_path))
|
138
|
+
end
|
139
|
+
|
140
|
+
def setupNotificationExtensionBundleId
|
141
|
+
suffix = "notification-extension"
|
142
|
+
debug_id = @main_target_build_settings_debug['PRODUCT_BUNDLE_IDENTIFIER']
|
143
|
+
release_id = @main_target_build_settings_release['PRODUCT_BUNDLE_IDENTIFIER']
|
144
|
+
setNotificationExtensionBuildSettings('PRODUCT_BUNDLE_IDENTIFIER', "#{debug_id}.#{suffix}", "#{release_id}.#{suffix}")
|
145
|
+
end
|
146
|
+
|
147
|
+
def setupMainTargetEntitlements
|
148
|
+
@logger.info("Setting up main target entitlements...")
|
149
|
+
setupEntitlements(@main_target_build_settings_debug, @main_target_build_settings_release, @main_target_name)
|
150
|
+
|
151
|
+
entitlements_path_debug = @main_target_build_settings_debug['CODE_SIGN_ENTITLEMENTS']
|
152
|
+
entitlements_path_release = @main_target_build_settings_release['CODE_SIGN_ENTITLEMENTS']
|
153
|
+
if entitlements_path_debug = entitlements_path_release
|
154
|
+
putStringValueIntoXML("aps-environment", "development", entitlements_path_debug)
|
155
|
+
else
|
156
|
+
putStringValueIntoXML("aps-environment", "development", entitlements_path_debug)
|
157
|
+
putStringValueIntoXML("aps-environment", "production", entitlements_path_release)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def setupNotificationExtensionEntitlements
|
162
|
+
@logger.info("Setting up extension entitlements...")
|
163
|
+
setupEntitlements(@extension_build_settings_debug, @extension_build_settings_release, @ne_target_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
def setupAppGroupPlistValue
|
167
|
+
putStringValueIntoXML("com.mobilemessaging.app_group", @app_group, @main_target_debug_plist)
|
168
|
+
putStringValueIntoXML("com.mobilemessaging.app_group", @app_group, @main_target_release_plist)
|
169
|
+
end
|
170
|
+
|
171
|
+
def setupBackgroundModesPlistValue
|
172
|
+
putKeyArrayElement("UIBackgroundModes", "remote-notification", @main_target_debug_plist)
|
173
|
+
putKeyArrayElement("UIBackgroundModes", "remote-notification", @main_target_release_plist)
|
174
|
+
end
|
175
|
+
|
176
|
+
def setupEmbedExtensionAction
|
177
|
+
phase_name = 'Embed App Extensions'
|
178
|
+
unless @main_target.copy_files_build_phases.select { |phase| phase.name == phase_name }.first
|
179
|
+
@logger.info("Adding copy files build phase: #{phase_name}")
|
180
|
+
new_phase = @main_target.new_copy_files_build_phase(phase_name)
|
181
|
+
new_phase.dst_subfolder_spec = '13'
|
182
|
+
new_phase.add_file_reference(@ne_target.product_reference)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def setupMainTargetDependency
|
187
|
+
unless @main_target.dependency_for_target(@ne_target)
|
188
|
+
@logger.info("Adding extension target dependency for main target")
|
189
|
+
@main_target.add_dependency(@ne_target)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def setupFrameworkSearchPaths
|
194
|
+
setNotificationExtensionBuildSettings('FRAMEWORK_SEARCH_PATHS', '$SRCROOT/$PROJECT/Plugins/com-infobip-plugins-mobilemessaging')
|
195
|
+
end
|
196
|
+
|
197
|
+
def setupRunpathSearchPaths
|
198
|
+
setNotificationExtensionBuildSettings('LD_RUNPATH_SEARCH_PATHS', '@executable_path/../../Frameworks')
|
199
|
+
end
|
200
|
+
|
201
|
+
def setupSwiftVersion
|
202
|
+
setNotificationExtensionBuildSettings('SWIFT_VERSION', @swift_version)
|
203
|
+
end
|
204
|
+
|
205
|
+
def setupProductName
|
206
|
+
setNotificationExtensionBuildSettings('PRODUCT_NAME', @ne_target_name)
|
207
|
+
end
|
208
|
+
|
209
|
+
def setupLibCordovaLink
|
210
|
+
lib_cordova_name = 'libCordova.a'
|
211
|
+
unless @ne_target.frameworks_build_phase.files_references.select { |ref| ref.path == lib_cordova_name }.first
|
212
|
+
@logger.info("Adding libCordova.a to Notification Extension target...")
|
213
|
+
ref = @main_target.frameworks_build_phase.files_references.select { |ref| ref.path == lib_cordova_name }.first
|
214
|
+
if ref
|
215
|
+
@ne_target.frameworks_build_phase.add_file_reference(ref)
|
216
|
+
else
|
217
|
+
@logger.error("Main target has no libCordova.a as a linked library. Unable to add libCordova.a to Notification Extension target!")
|
218
|
+
end
|
219
|
+
else
|
220
|
+
@logger.info("Notification Extension target already has libCordova.a linked.")
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def setupCopyFrameworkScript
|
225
|
+
phase_name = "Copy Frameworks"
|
226
|
+
shell_script = "/usr/local/bin/carthage copy-frameworks"
|
227
|
+
unless @main_target.shell_script_build_phases.select { |phase| phase.shell_script == shell_script }.first
|
228
|
+
@logger.info("Setting up #{phase_name} shell script for main target")
|
229
|
+
phase = @main_target.new_shell_script_build_phase(phase_name)
|
230
|
+
phase.shell_path = "/bin/sh"
|
231
|
+
phase.shell_script = shell_script
|
232
|
+
phase.input_paths << "$SRCROOT/$PROJECT/Plugins/com-infobip-plugins-mobilemessaging/MobileMessaging.framework"
|
233
|
+
phase.output_paths << "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/MobileMessaging.framework"
|
234
|
+
else
|
235
|
+
@logger.info("Main target already has #{phase_name} shell script set up")
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def setupEntitlements(_build_settings_debug, _build_settings_release, target_name)
|
240
|
+
entitlements_debug_filepath = _build_settings_debug['CODE_SIGN_ENTITLEMENTS'] != nil ? resolveAbsolutePath(_build_settings_debug['CODE_SIGN_ENTITLEMENTS']) : nil
|
241
|
+
entitlements_release_filepath = _build_settings_release['CODE_SIGN_ENTITLEMENTS'] != nil ? resolveAbsolutePath(_build_settings_release['CODE_SIGN_ENTITLEMENTS']) : nil
|
242
|
+
key = 'CODE_SIGN_ENTITLEMENTS'
|
243
|
+
if entitlements_debug_filepath == nil and entitlements_release_filepath == nil
|
244
|
+
@logger.info("\tEntitlements are not set for both release and debug schemes, setting up...")
|
245
|
+
entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}.entitlements")
|
246
|
+
entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
|
247
|
+
|
248
|
+
@logger.info("\tSetting build settings:\n\t\tdebug: \t#{key}\t#{entitlements_destination_filepath}\n\t\trelease:\t#{key}\t#{entitlements_destination_filepath}")
|
249
|
+
|
250
|
+
_build_settings_debug[key] = entitlements_destination_filepath
|
251
|
+
_build_settings_release[key] = entitlements_destination_filepath
|
252
|
+
else
|
253
|
+
if entitlements_debug_filepath == entitlements_release_filepath
|
254
|
+
@logger.info("\tEntitlements settings are equal for debug and release schemes.")
|
255
|
+
putAppGroupEntitlement(entitlements_debug_filepath)
|
256
|
+
else
|
257
|
+
if entitlements_debug_filepath != nil
|
258
|
+
@logger.info("\tEntitlements debug settings already set, updating settings...")
|
259
|
+
putAppGroupEntitlement(entitlements_debug_filepath)
|
260
|
+
else
|
261
|
+
@logger.info("\tEntitlements debug settings are not set, setting up...")
|
262
|
+
entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}_debug.entitlements")
|
263
|
+
entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
|
264
|
+
|
265
|
+
@logger.info("\tSetting build settings:\n\tdebug:\t#{key}\t#{entitlements_destination_filepath}")
|
266
|
+
_build_settings_debug[key] = entitlements_destination_filepath
|
267
|
+
end
|
268
|
+
|
269
|
+
if entitlements_release_filepath != nil
|
270
|
+
@logger.info("\tEntitlements release settings already set, updating settings...")
|
271
|
+
putAppGroupEntitlement(entitlements_release_filepath)
|
272
|
+
else
|
273
|
+
@logger.info("\tEntitlements release settings are not set, setting up...")
|
274
|
+
entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}_release.entitlements")
|
275
|
+
entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
|
276
|
+
|
277
|
+
@logger.info("\tSetting build settings:\n\trelease:\t#{key}\t#{entitlements_destination_filepath}")
|
278
|
+
_build_settings_release[key] = entitlements_destination_filepath
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def setupExtensionTargetCapabilities
|
285
|
+
exitsting_capabilities = @project.root_object.attributes["TargetAttributes"][@ne_target.uuid]
|
286
|
+
mobilemessaging_capabilities = { "SystemCapabilities" =>
|
287
|
+
{
|
288
|
+
"com.apple.ApplicationGroups.iOS" => { "enabled" => 1 }
|
289
|
+
}
|
290
|
+
}
|
291
|
+
if exitsting_capabilities == nil
|
292
|
+
@project.root_object.attributes["TargetAttributes"][@ne_target.uuid] = mobilemessaging_capabilities
|
293
|
+
else
|
294
|
+
@project.root_object.attributes["TargetAttributes"][@ne_target.uuid] = exitsting_capabilities.merge(mobilemessaging_capabilities)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def setupMainTargetCapabilities
|
299
|
+
exitsting_capabilities = @project.root_object.attributes["TargetAttributes"][@main_target.uuid]
|
300
|
+
mobilemessaging_capabilities = { "SystemCapabilities" =>
|
301
|
+
{
|
302
|
+
"com.apple.ApplicationGroups.iOS" => { "enabled" => 1 },
|
303
|
+
"com.apple.Push" => { "enabled" => 1 },
|
304
|
+
"com.apple.BackgroundModes" => { "enabled" => 1 }
|
305
|
+
}
|
306
|
+
}
|
307
|
+
if exitsting_capabilities == nil
|
308
|
+
@project.root_object.attributes["TargetAttributes"][@main_target.uuid] = mobilemessaging_capabilities
|
309
|
+
else
|
310
|
+
@project.root_object.attributes["TargetAttributes"][@main_target.uuid] = exitsting_capabilities.merge(mobilemessaging_capabilities)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def resolveXcodePath(path)
|
315
|
+
return path.sub(@project_dir, '$(PROJECT_DIR)')
|
316
|
+
end
|
317
|
+
|
318
|
+
def setNotificationExtensionBuildSettings(key, debug_value, release_value=nil)
|
319
|
+
release_value = release_value != nil ? release_value : debug_value
|
320
|
+
@logger.info("\tSetting extension build settings:\n\t\tdebug: \t#{key}\t#{debug_value}\n\t\trelease:\t#{key}\t#{release_value}")
|
321
|
+
@extension_build_settings_debug[key] = debug_value
|
322
|
+
@extension_build_settings_release[key] = release_value
|
323
|
+
end
|
324
|
+
|
325
|
+
def getNotificationExtensionGroupReference
|
326
|
+
group_reference = @project.groups().select { |group| group.name == @extension_group_name }.first
|
327
|
+
if group_reference == nil
|
328
|
+
group_reference = @project.new_group(@extension_group_name, @extension_destination_dir)
|
329
|
+
end
|
330
|
+
return group_reference
|
331
|
+
end
|
332
|
+
|
333
|
+
def createAppGroupEntitlements(_entitlements_name)
|
334
|
+
entitlements_destination_filepath = File.join(@project_dir, _entitlements_name)
|
335
|
+
entitlements_source_filepath = File.join(Mmine.root, 'resources', "MobileMessagingNotificationExtension.entitlements")
|
336
|
+
unless File.exist?(entitlements_destination_filepath)
|
337
|
+
@logger.info("\tCopying entitlemenst file to path: #{entitlements_destination_filepath}")
|
338
|
+
FileUtils.cp(entitlements_source_filepath, entitlements_destination_filepath)
|
339
|
+
ref = @project.main_group.new_reference(entitlements_destination_filepath)
|
340
|
+
ref.last_known_file_type = "text.xml"
|
341
|
+
else
|
342
|
+
@logger.info("\tEntitlements file already exists on path: #{entitlements_destination_filepath}")
|
343
|
+
end
|
344
|
+
putAppGroupEntitlement(entitlements_destination_filepath)
|
345
|
+
return entitlements_destination_filepath
|
346
|
+
end
|
347
|
+
|
348
|
+
def resolveAbsolutePath(path)
|
349
|
+
ret = path
|
350
|
+
["$(PROJECT_DIR)", "$PROJECT_DIR"].each do |proj_dir|
|
351
|
+
ret = ret.sub(proj_dir, @project_dir)
|
352
|
+
end
|
353
|
+
|
354
|
+
if ret.include?("$")
|
355
|
+
puts "Could not resolve absolute path for #{path}. The only supported variable are $(PROJECT_DIR) and $PROJECT_DIR. Make sure you don't misuse Xcode paths variables, consider using $(PROJECT_DIR) instead or contact Infobip Mobile Messaging support via email Push.Support@infobip.com"
|
356
|
+
exit
|
357
|
+
end
|
358
|
+
|
359
|
+
if ret == path && !ret.include?("$") # no aliases found/replaced, no aliases left in path
|
360
|
+
if path.start_with? "/"
|
361
|
+
return path # it's already an absolute path
|
362
|
+
else
|
363
|
+
return File.join(@project_dir, path) # it's a relative project path
|
364
|
+
end
|
365
|
+
end
|
366
|
+
return ret
|
367
|
+
end
|
368
|
+
|
369
|
+
def putStringValueIntoXML(key, value, plist_path)
|
370
|
+
plist_path = resolveAbsolutePath(plist_path)
|
371
|
+
@logger.info("\tConfiguring plist on path: #{plist_path}")
|
372
|
+
doc = Nokogiri::XML(IO.read(plist_path))
|
373
|
+
key_node = doc.search("//dict//key[text() = '#{key}']").first
|
374
|
+
string_value_node = Nokogiri::XML::Node.new("string",doc)
|
375
|
+
string_value_node.content = value
|
376
|
+
if key_node == nil
|
377
|
+
@logger.info("\tAdding 'key' node with content #{key}")
|
378
|
+
key_node = Nokogiri::XML::Node.new("key",doc)
|
379
|
+
key_node.content = key
|
380
|
+
doc.xpath("//dict").first.add_child(key_node)
|
381
|
+
@logger.info("\tAdding next string sibling with content #{string_value_node}")
|
382
|
+
key_node.add_next_sibling(string_value_node)
|
383
|
+
else
|
384
|
+
@logger.info("\t'Key' node with content #{key} already extists.")
|
385
|
+
existing_string_value_node = key_node.xpath("following-sibling::*").first
|
386
|
+
if existing_string_value_node.name == 'string'
|
387
|
+
@logger.info("\tUpdating following string sibling value with #{value}")
|
388
|
+
existing_string_value_node.content = value
|
389
|
+
else
|
390
|
+
@logger.info("\tAdding next string sibling with content #{string_value_node}")
|
391
|
+
key_node.add_next_sibling(string_value_node)
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
file = File.open(plist_path,'w')
|
396
|
+
@logger.info("\tWriting changes to plist: #{plist_path}")
|
397
|
+
file.puts Nokogiri::XML(doc.to_xml) { |x| x.noblanks }
|
398
|
+
file.close
|
399
|
+
end
|
400
|
+
|
401
|
+
def putKeyArrayElement(key, value, filepath) # check if it appends to existing array
|
402
|
+
doc = Nokogiri::XML(IO.read(filepath))
|
403
|
+
key_node = doc.search("//dict//key[text() = '#{key}']").first
|
404
|
+
string_app_group_value = Nokogiri::XML::Node.new("string",doc)
|
405
|
+
string_app_group_value.content = value
|
406
|
+
if key_node == nil
|
407
|
+
@logger.info("\tAdding 'key' node with content #{key}")
|
408
|
+
key_node = Nokogiri::XML::Node.new("key",doc)
|
409
|
+
key_node.content = key
|
410
|
+
array_node = Nokogiri::XML::Node.new("array",doc)
|
411
|
+
array_node.add_child(string_app_group_value)
|
412
|
+
|
413
|
+
doc.xpath("//dict").first.add_child(key_node)
|
414
|
+
key_node.add_next_sibling(array_node)
|
415
|
+
else
|
416
|
+
@logger.info("\t'Key' node with content #{key} already extists.")
|
417
|
+
array_node = key_node.xpath("following-sibling::*").first
|
418
|
+
if array_node.name == 'array'
|
419
|
+
@logger.info("\tFollowing array sibling already exists")
|
420
|
+
unless array_node.xpath("//string[text() = '#{value}']").first
|
421
|
+
@logger.info("\tAdding child string element with content #{value}")
|
422
|
+
array_node.add_child(string_app_group_value)
|
423
|
+
else
|
424
|
+
@logger.info("\tArray string element with content #{value} already exists")
|
425
|
+
end
|
426
|
+
else
|
427
|
+
@logger.info("\tFollowing array sibling is missing. Adding array node containing a string element.")
|
428
|
+
array_node = Nokogiri::XML::Node.new("array",doc)
|
429
|
+
array_node.add_child(string_app_group_value)
|
430
|
+
key_node.add_next_sibling(array_node)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
file = File.open(filepath,'w')
|
435
|
+
@logger.info("\tWriting changes to entitlements: #{filepath}")
|
436
|
+
file.puts Nokogiri::XML(doc.to_xml) { |x| x.noblanks }
|
437
|
+
file.close
|
438
|
+
end
|
439
|
+
|
440
|
+
def putAppGroupEntitlement(filepath)
|
441
|
+
putKeyArrayElement("com.apple.security.application-groups", @app_group, filepath)
|
442
|
+
end
|
443
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>com.apple.security.application-groups</key>
|
6
|
+
<array>
|
7
|
+
</array>
|
8
|
+
</dict>
|
9
|
+
</plist>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
7
|
+
<key>CFBundleDisplayName</key>
|
8
|
+
<string>MobileMessagingNotificationExtension</string>
|
9
|
+
<key>CFBundleExecutable</key>
|
10
|
+
<string>$(EXECUTABLE_NAME)</string>
|
11
|
+
<key>CFBundleIdentifier</key>
|
12
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
13
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
14
|
+
<string>6.0</string>
|
15
|
+
<key>CFBundleName</key>
|
16
|
+
<string>$(PRODUCT_NAME)</string>
|
17
|
+
<key>CFBundlePackageType</key>
|
18
|
+
<string>XPC!</string>
|
19
|
+
<key>CFBundleShortVersionString</key>
|
20
|
+
<string>1.0</string>
|
21
|
+
<key>CFBundleVersion</key>
|
22
|
+
<string>1</string>
|
23
|
+
<key>NSExtension</key>
|
24
|
+
<dict>
|
25
|
+
<key>NSExtensionPointIdentifier</key>
|
26
|
+
<string>com.apple.usernotifications.service</string>
|
27
|
+
<key>NSExtensionPrincipalClass</key>
|
28
|
+
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
29
|
+
</dict>
|
30
|
+
</dict>
|
31
|
+
</plist>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
// NotificationService.swift
|
2
|
+
|
3
|
+
import UserNotifications
|
4
|
+
import MobileMessaging
|
5
|
+
|
6
|
+
@available(iOS 10.0, *)
|
7
|
+
class NotificationService: UNNotificationServiceExtension {
|
8
|
+
|
9
|
+
var contentHandler: ((UNNotificationContent) -> Void)?
|
10
|
+
var originalContent: UNNotificationContent?
|
11
|
+
|
12
|
+
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
|
13
|
+
self.contentHandler = contentHandler
|
14
|
+
self.originalContent = request.content
|
15
|
+
MobileMessagingNotificationServiceExtension.startWithApplicationCode(<# put your Application Code here #>)
|
16
|
+
MobileMessagingNotificationServiceExtension.didReceive(request, withContentHandler: contentHandler)
|
17
|
+
}
|
18
|
+
|
19
|
+
override func serviceExtensionTimeWillExpire() {
|
20
|
+
MobileMessagingNotificationServiceExtension.serviceExtensionTimeWillExpire()
|
21
|
+
if let originalContent = originalContent {
|
22
|
+
contentHandler?(originalContent)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mmine
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrey Kadochnikov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: xcodeproj
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.6.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.8.5
|
41
|
+
description: Use this tool to automatically integrate your Xcode project with Infobips
|
42
|
+
(https://www.infobip.com) Notification Service Extension
|
43
|
+
email: andrey.kadochnikov@infobip.com
|
44
|
+
executables:
|
45
|
+
- mmine
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- bin/mmine
|
50
|
+
- lib/mmine.rb
|
51
|
+
- lib/mmine/notification_extension_integrator.rb
|
52
|
+
- lib/mmine/version.rb
|
53
|
+
- resources/MobileMessagingNotificationExtension.entitlements
|
54
|
+
- resources/MobileMessagingNotificationServiceExtension.plist
|
55
|
+
- resources/NotificationService.swift
|
56
|
+
homepage: https://github.com/infobip/mobile-messaging-mmine
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata:
|
60
|
+
source_code_url: https://github.com/infobip/mobile-messaging-mmine
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.7.7
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Mobile Messaging iOS Notification Extension Integration Tool made at Infobip
|
81
|
+
(https://www.infobip.com)!!!
|
82
|
+
test_files: []
|