Bug 43985 - Loading images in UNNotificationServiceExtension doesn't work
Summary: Loading images in UNNotificationServiceExtension doesn't work
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: XI 9.99 (iOS 10 previews)
Hardware: PC Mac OS
: Normal normal
Target Milestone: Future Cycle (TBD)
Assignee: Rolf Bjarne Kvinge [MSFT]
URL:
: 46968 58566 (view as bug list)
Depends on: 56022
Blocks:
  Show dependency tree
 
Reported: 2016-09-03 18:13 UTC by Konstantin
Modified: 2018-03-19 22:49 UTC (History)
17 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Device log iPhone 6s Plus (65.01 KB, text/plain)
2017-04-26 08:20 UTC, Luigi Saggese
Details
Verbosity Log (1.82 MB, text/plain)
2017-04-28 07:15 UTC, Luigi Saggese
Details
Zip with extensions (1.91 MB, application/zip)
2017-04-28 08:24 UTC, Luigi Saggese
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description Konstantin 2016-09-03 18:13:02 UTC
Hello Xamarin,

 * var data = NSData.FromUrl(NSUrl.FromString("https://i.ytimg.com/vi/tntOCGkgt98/maxresdefault.jpg"));
 * var task = NSUrlSession.SharedSession.CreateDataTask(NSUrl.FromString("https://i.ytimg.com/vi/tntOCGkgt98/maxresdefault.jpg"));
 * var data = new WebClient().DownloadData("https://i.ytimg.com/vi/tntOCGkgt98/maxresdefault.jpg");

Any of these 3 statements just kill the UNNotificationServiceExtension. I.e. execution of extension is just stopped: contentHandler(..) hasn't been called, etc. **Without loading images** service extension works fine (i.e. I can modify body & title of the notification).

I've already tried to wrap these statements into try-catch (with modification of the notification in case of failure, etc.) - but "catch" doesn't fire.

Test project can be found here: https://www.dropbox.com/s/gyz6szbpv0ip6h0/xamarin-service-extension_images_loader.zip?dl=0 

Best,
Konstantin

===================
info.plist of the Service Extension:

	<?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>CFBundleDisplayName</key>
		<string>ServiceExtension</string>
		<key>CFBundleName</key>
		<string>ServiceExtension</string>
		<key>CFBundleIdentifier</key>
		<string>com.mybundle.serviceextension</string>
		<key>CFBundleDevelopmentRegion</key>
		<string>en</string>
		<key>CFBundleInfoDictionaryVersion</key>
		<string>6.0</string>
		<key>CFBundlePackageType</key>
		<string>XPC!</string>
		<key>CFBundleShortVersionString</key>
		<string>42.0</string>
		<key>CFBundleVersion</key>
		<string>371</string>
		<key>MinimumOSVersion</key>
		<string>10.0</string>
		<key>NSAppTransportSecurity</key>
		<dict>
			<key>NSAllowsArbitraryLoads</key>
			<true/>
		</dict>
		<key>NSExtension</key>
		<dict>
			<key>NSExtensionPrincipalClass</key>
			<string>NotificationService</string>
			<key>NSExtensionPointIdentifier</key>
			<string>com.apple.usernotifications.service</string>
		</dict>
	</dict>
	</plist>

===================
Xamarin Studio information:

=== Xamarin Studio Community ===

Version 6.1 (build 5383)
Installation UUID: fb0e4a2c-12e9-4806-bfb9-5183f291bd0e
Runtime:
	Mono 4.6.0 (mono-4.6.0-branch/3ed2bba) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 406000182

=== NuGet ===

Version: 3.4.3.0

=== Xamarin.Profiler ===

Not Installed

=== Apple Developer Tools ===

Xcode 8.0 (11228.2)
Build 8S193k

=== Xamarin.iOS ===

Version: 9.99.5.54 (Xamarin Studio Community)
Hash: 974ea0b
Branch: cycle8
Build date: 2016-08-30 18:12:06-0400

=== Xamarin.Android ===

Not Installed

=== Xamarin Android Player ===

Not Installed

=== Xamarin.Mac ===

Not Installed

=== Build Information ===

Release ID: 601005383
Git revision: 37159a7d0c1ed6c9f661210879e9e233ca92e65d
Build date: 2016-08-30 22:07:20-04
Xamarin addins: 00a35f60101b50c8fa28b2b8c0e5b8ade85f7083
Build lane: monodevelop-lion-cycle8

=== Operating System ===

Mac OS X 10.11.6
Darwin Konstantins-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0
    Thu Jun 23 18:25:34 PDT 2016
    root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64
Comment 1 Rolf Bjarne Kvinge [MSFT] 2016-09-05 08:59:50 UTC
Just running the iOS app doesn't seem to trigger the extensions; is there anything else I need to do to reproduce this?
Comment 2 Alex Soto [MSFT] 2016-09-05 15:13:35 UTC
Hello Konstantin

I am not able to reproduce your issue, If I run your sample unchanged and trigger a remote notification I am able to see the remote image on the notification. Even I changed it to our Xamagon just to make sure it was working.

http://imgur.com/9OjGLjn
http://imgur.com/xOUZ6KL

My current setup is 

    Xamarin.iOS: using latest xcode8 build from here https://github.com/xamarin/xamarin-macios/wiki [1]
    iPhone 6 plus on iOS 10 beta 8 (14A5346a)
    Xcode 8.0 beta 6 (8S201h)

Please could you try the build mentioned above to see if it solves your issue? If it doesn't could you please check that your device is up to date with the latest beta bits and so does your Xcode? It seems you are using beta 5 from the logs you posted :)

Cheers!

[1]: https://bosstoragemirror.blob.core.windows.net/wrench/macios-mac-xcode8/6c/6cf2cf6c1699cab13c2af4f05d63136e3a6a7da7/xamarin.ios-9.99.5.107.pkg
Comment 3 Konstantin 2016-09-05 15:50:28 UTC
Updated everything I could, still nothing:

=== Xamarin Studio Community ===

Version 6.1 (build 5383)
Installation UUID: fb0e4a2c-12e9-4806-bfb9-5183f291bd0e
Runtime:
	Mono 4.6.0 (mono-4.6.0-branch/3ed2bba) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 406000182

=== NuGet ===

Version: 3.4.3.0

=== Xamarin.Profiler ===

Not Installed

=== Apple Developer Tools ===

Xcode 8.0 (11239.2)
Build 8S201h

=== Xamarin.iOS ===

Version: 9.99.5.107 (Xamarin Studio Community)
Hash: 6cf2cf6
Branch: cycle8
Build date: 2016-09-04 13:45:01-0400

=== Xamarin.Android ===

Not Installed

=== Xamarin Android Player ===

Not Installed

=== Xamarin.Mac ===

Not Installed

=== Build Information ===

Release ID: 601005383
Git revision: 37159a7d0c1ed6c9f661210879e9e233ca92e65d
Build date: 2016-08-30 22:07:20-04
Xamarin addins: 00a35f60101b50c8fa28b2b8c0e5b8ade85f7083
Build lane: monodevelop-lion-cycle8

=== Operating System ===

Mac OS X 10.11.6
Darwin Konstantins-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0
    Thu Jun 23 18:25:34 PDT 2016
    root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64
Comment 4 Rolf Bjarne Kvinge [MSFT] 2016-09-06 13:44:06 UTC
So I think I know what's happening: the extension is running into a memory limit, and it's killed.
 
In my case a JetsamEvent-* report is generated when the extension terminates, and something like this is listed:
 
  {
    "uuid" : "ba54c910-531c-32e5-878e-129865039de0",
    "states" : [
      "frontmost"
    ],
    "killDelta" : 7652,
    "lifetimeMax" : 873,
    "age" : 155281267,
    "purgeable" : 1,
    "fds" : 50,
    "genCount" : 0,
    "coalition" : 78,
    "rpages" : 384,
    "reason" : "per-process-limit",
    "pid" : 6366,
    "idleDelta" : 9,
    "name" : "ServiceExtension",
    "cpuTime" : 0.202007
  },
 
in particular, the "reason: per-process-limit" is telling that something hit a limit and the executable was terminated.
 
I'm not sure why it works for Alex though.
 
We're obviously working continuously to minimize the memory footprint in Xamarin apps, but at this point there won't be any fixes in this area before the final iOS 10 release in a few days. So maybe there are other approaches you can use? Maybe download and cache images from the main app, and then just load that file from the extension (or are there too many possible images)?
Comment 5 Sebastien Pouliot 2016-09-06 13:56:47 UTC
Apple exact heuristics are not documented (e.g. they could vary by device types, like total memory) and also subject to change.

Beside Rolf's suggestion (to delegate work to the main app) be aware that there's a huge difference between XI debug and release builds. It's worth checking if the later works for your use case.
Comment 6 Sebastien Pouliot 2016-10-05 14:22:00 UTC
Under investigation
Comment 7 Marko 2016-11-14 14:50:47 UTC
The service extension doesn't even work at all on my iPhone SE, while it's working (sometimes, there's a 50:50 chance) on an iPhone 5.

Here's the error:

Nov 14 15:28:07 Markos-iPhone-SE SpringBoard(Foundation)[57] <Notice>: tearing down extension request for pid 413
Nov 14 15:28:07 Markos-iPhone-SE SpringBoard(UserNotificationsServer)[57] <Error>: Extension error whilst trying to modify push notification EE0E-9BAC: Error Domain=NSCocoaErrorDomain Code=4097 "connection from pid 413" UserInfo={NSDebugDescription=connection from pid 413}
Nov 14 15:28:07 Markos-iPhone-SE SpringBoard(Foundation)[57] <Notice>: extension connection was interrupted
Nov 14 15:28:07 Markos-iPhone-SE SpringBoard(UserNotificationsServer)[57] <Notice>: [com.markobl.tickerfeed] Saving notification EE0E-9BAC
Nov 14 15:28:07 Markos-iPhone-SE SpringBoard(UserNotificationsServer)[57] <Notice>: Saving notification list at /var/mobile/Library/SpringBoard/PushStore/com.markobl.tickerfeed.pushstore with 3 items
Comment 8 Rolf Bjarne Kvinge [MSFT] 2016-11-14 15:28:57 UTC
@Marko, what do you do in your service extension? Apple has set a very low memory limit for it :(
Comment 9 Marko 2016-11-14 15:36:40 UTC
I'm doing nothing special, just like the sample from the first post, I download an image and save it. And the images are really small (140x140 px).

...
var data = NSData.FromUrl (url);
if (data != null) {
	data.Save (imageFile, true);
	...
}

As I said: It's not working at all on my iPhone SE. On my iPhone 5, it's working with a 50:50 chance.

What's really strange: I cache the images, but even than (by just using the cached file, no download involved), there's only a 50:50 change on the iPhone 5 that the extension works.
Comment 10 Alex Soto [MSFT] 2016-11-15 06:38:45 UTC
*** Bug 46968 has been marked as a duplicate of this bug. ***
Comment 11 Marko 2016-11-15 10:23:49 UTC
Btw. would it be possible to embed native extensions into Xamarin? Actually, the code is ~20 lines of code (it should be the same with Objective-C or Swift) and I guess other extensions won't need much more code. Therefore, if possible, I would simply write it in Swift and embed it into the Xamarin app. Maybe hacky, but the only useful solution to the very low memory limit.
Comment 12 Rolf Bjarne Kvinge [MSFT] 2016-11-15 17:13:12 UTC
@Marko, yes, it's possible to embed extensions written in Xcode using Swift or Objective-C in Xamarin apps, but it's a cumbersome process.

It boils down to this:

a) Build your Xcode project.
b) Build your Xamarin solution.
c) Copy the Xcode extensions to the expected locations in the resulting Xamarin app bundle.
d) Resign the app bundle (you can copy-paste the codesign statements from the Xamarin solution's build log).

And when building for distribution, you'll have to unzip the .ipa after b) and re-zip it when done.

If you're using Swift, you'll also have to make sure to copy the Swift libraries where the extensions expect them to be (they end up both in the .app and in the .ipa (in a different location)).
Comment 13 Marko 2016-11-16 14:17:22 UTC
Thanks for the tip, Rolf.

Is it possible to use the native extension in the debug or release mode too? 

What I have done: I build the Xcode project (it's Objective-C, so no need to copy Swift libraries) in debug mode, copied the Plugins folder + all files into the "Resource" folder of the Xamarin project and resigned it (with the command from building the Xamarin extension). Then I removed the Xamarin extension.

So, when I build the solution, all the files are in the correct place. But when I try to run it on the device, I get the following error: notificationextension.appex : 0xe8008019 (The application does not have a valid signature.)

I triple-checked all the provision profiles and everything is correct and I resigned the extension. I also didn't see anything in the logs, when I build the Xamarin extension, that's done after the extension is signed, expect for copying it.

Is there anything that I'm missing here?
Comment 14 Rolf Bjarne Kvinge [MSFT] 2016-11-16 14:23:25 UTC
(In reply to Marko from comment #13)
> 
> What I have done: I build the Xcode project (it's Objective-C, so no need to
> copy Swift libraries) in debug mode, copied the Plugins folder + all files
> into the "Resource" folder of the Xamarin project and resigned it (with the
> command from building the Xamarin extension). Then I removed the Xamarin
> extension.

You have to reorder a bit: the last thing you do is to resign (removing files also means the signature is invalidated).

Also the extensions have to be signed separately (and before signing the whole app, since doing any file modification in any file in the .app invalidates the signature, and this includes code signing a directory in the app).

You can check a signature before uploading like this:

    codesign --verify path/to/file

so to check that the appex signature is valid:

    codesign --verify path/to/notificationextension.appex
Comment 15 Marko 2016-11-16 14:35:05 UTC
Awesome, it's working now :) As you said, the signature was invalid. I just resigned the extension in the Debug folder, hit the run button and it just worked.

Now, the most important question: Is there a way to automate the resign in Xamarin Studio, so I don't have to do this on my own? If it's possible, it's really a piece of cake to use a native extension (without zipping and unzipping the ipa e.g.).
Comment 16 Mat 2016-11-21 20:28:33 UTC
I have the same issue I think. I can use the Notification service extension to change title/body and it works fine, but as soon as I call .Resume() on the NSURLSession I am using to download a very small image (9kb), the extension is killed.

Logs when the extension is killed are exactly the same as Marko posted in Comment #7. https://bugzilla.xamarin.com/show_bug.cgi?id=43985#c7
Comment 17 Jerome Laban 2016-11-21 20:33:53 UTC
I have this issue as well.
Comment 18 Rolf Bjarne Kvinge [MSFT] 2016-11-22 09:39:51 UTC
 (In reply to Marko from comment #15)
> Awesome, it's working now :) As you said, the signature was invalid. I just
> resigned the extension in the Debug folder, hit the run button and it just
> worked.

Great :)

> Now, the most important question: Is there a way to automate the resign in
> Xamarin Studio, so I don't have to do this on my own? If it's possible, it's
> really a piece of cake to use a native extension (without zipping and
> unzipping the ipa e.g.).

I think you can do this using custom MSBuild tasks in your project file.

In particular I think you can define a "BeforeCodesign" [1] task that copies your Objective-C extensions into the app and signs them.

[1] https://github.com/xamarin/xamarin-macios/blob/e84bbb9cf10a18d4d4ae36cbb99623784b5b3588/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets#L314
Comment 19 Bob 2017-04-25 16:59:25 UTC
Marko...how exactly did you resign the extension? Shouldn't this be automatic via the provisioning profile setup?  Can you provide some detail as I am having the same issue.

Thanks
bob
Comment 20 Rolf Bjarne Kvinge [MSFT] 2017-04-25 17:03:25 UTC
@Bob, resigning is only required if you write the extension in Objective-C or Swift, and then want to embed that extension in the Xamarin.iOS app.

If you're having the same problem, the fix is to use less memory (which can be verify difficult, since the memory limit is quite low).

Alternatively you can do as others have done, and write the extension in Swift/Objective-C (please read the entire bug, the exact process is described in other comments).
Comment 21 Bob 2017-04-25 17:28:09 UTC
Rolf....the code for a notifcation extension is so small and it only grabs 9kb image.  What else can one do to minimize memory?
Comment 22 Luigi Saggese 2017-04-25 22:27:06 UTC
Same issue here:

http://stackoverflow.com/questions/41428243/xamarin-notification-service-extension-issue

Is it in roadmap to fix this issue?
Comment 23 Bob 2017-04-25 23:42:00 UTC
Luigi and I are seeing this

Apr 26 00:12:57 iPhone SpringBoard(UserNotificationsServer)[53] <Error>: Extension error whilst trying to modify push notification E832-1C1F: Error Domain=NSCocoaErrorDomain Code=4097 "connection from pid 964" UserInfo={NSDebugDescription=connection from pid 964}
Apr 26 00:12:57 iPhone SpringBoard(Foundation)[53] <Notice>: tearing down extension request for pid 0



If we remove the attachment code and only modify body or title, it works on any device.  However, the attachment code is causing to stop (like Marko demonstrated).  

The mystery to me is why the attachment code works on my iphone 6 but not on the SE or 7.  What are the newer devices doing in terms of MM that the 6 is not.
Comment 24 Luigi Saggese 2017-04-26 08:20:48 UTC
Created attachment 21787 [details]
Device log iPhone 6s Plus

This is my log when i receive rich push notification
Comment 25 Rolf Bjarne Kvinge [MSFT] 2017-04-26 15:38:00 UTC
@Luigi, we're planning to fix this (as far as it can be fixed: as long as iOS enforces a memory limit you can always hit the limit if you so desire by just loading a bigger image), however we don't have an exact date yet.

Maybe if you try building for release and test that it works (debug builds use more memory than release builds); if you're lucky you'll get below the limit.

If you attach your code, I might also be able to offer suggestions what you can do to minimize memory usage.
Comment 26 Luigi Saggese 2017-04-26 16:30:09 UTC
@Rolf, my test is made on relase build and i'm not lucky (maybe in love :-P ).
Anyway if you check my 

http://stackoverflow.com/questions/41428243/xamarin-notification-service-extension-issue

Stackoverflow question, attached there is code.


Thanks for your help.
Comment 27 Bob 2017-04-26 16:32:18 UTC
Rolf..here's my notif service code:

using System;
using Foundation;
using UserNotifications;

namespace notifications
{
	[Register ("NotificationService")]
	public class NotificationService : UNNotificationServiceExtension
	{
		UNMutableNotificationContent BestAttemptContent { get; set; }
		public Action<UNNotificationContent> ContentHandler { get; set; }

		protected NotificationService (IntPtr handle) : base (handle)
		{
			// Note: this .ctor should not contain any initialization logic.
		}

		public override void DidReceiveNotificationRequest (UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
		{
				string imageURL = null;
				NSError err = null;

				ContentHandler = contentHandler;
				BestAttemptContent = request.Content.MutableCopy () as UNMutableNotificationContent;

				if (BestAttemptContent != null) {
					if (BestAttemptContent.UserInfo.ContainsKey (new NSString ("pushImage"))) {
						imageURL = BestAttemptContent.UserInfo.ValueForKey (new NSString ("pushImage")).ToString ();
					}

					if (imageURL == null) {
						contentHandler (BestAttemptContent);
						return;
					}

					var url = new NSUrl (imageURL.ToString ());

					//this works
					//var surl = NSBundle.MainBundle.GetUrlForResource ("P", "png");

					//temp path doesn't seem to want to work
					//var tmp = System.IO.Path.GetTempPath ();
					//var attachmentURL = NSUrl.CreateFileUrl (tmp +  url.LastPathComponent, false, null);

					var cache = NSSearchPath.GetDirectories (NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User, true);
					var attachmentURL = NSUrl.CreateFileUrl (cache [0] + "/" + url.LastPathComponent, false, null);

					NSUrlSession.SharedSession.CreateDownloadTask (url, (tempfile, response, error) => {

							if (error != null) {
								BestAttemptContent.Body = "0";
								contentHandler (BestAttemptContent);
								return;
							}
							if (tempfile == null) {
								BestAttemptContent.Body = "1";
								contentHandler (BestAttemptContent);
								return;
							}

							NSFileManager.DefaultManager.Move (tempfile, attachmentURL, out err);
							if (err != null) {
								contentHandler (BestAttemptContent);
								return;
							}

							// Create attachment;
							var options = new UNNotificationAttachmentOptions ();
							var attachment = UNNotificationAttachment.FromIdentifier ("", attachmentURL, options, out err);

							if (err != null) {
								contentHandler (BestAttemptContent);
								return;
							}
							BestAttemptContent.Body = "Dasffafasdfdsfa";
							BestAttemptContent.Attachments = new UNNotificationAttachment [] { attachment };
				
							contentHandler (BestAttemptContent);

					}).Resume ();


				} else {
					// Display notification
					contentHandler (BestAttemptContent);
				}
		}

		public override void TimeWillExpire ()
		{
			// Called just before the extension will be terminated by the system.
			// Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
			ContentHandler (BestAttemptContent);
		}
	}
}
Comment 28 Rolf Bjarne Kvinge [MSFT] 2017-04-27 06:00:02 UTC
@Bob, that looks about as good as it can get. My suggestion for the moment would be to write the extension in Objective-C/Swift if you want to download images (http://stackoverflow.com/a/43647608/183422).
Comment 29 Luigi Saggese 2017-04-27 07:38:30 UTC
@Rolf, really thanks for your answer on stackoverflow is very detailed! Today i will test it and i let you know if all works fine.
Comment 30 Rolf Bjarne Kvinge [MSFT] 2017-04-27 07:47:01 UTC
@Luigi, the stack overflow answer isn't mine :) But you're right, it's a good answer.
Comment 31 Luigi Saggese 2017-04-27 16:51:22 UTC
@Rolf, 	
I have archived for publish my app -> Signing and distribute with same certificate used to sign Obj extension. 

Now I have unzipped ipa generated and replaced appex. Compressed and renamed as ipa. Now i have used this tool to resign application (github.com/maciekish/iReSign). Maybe there are issue to resign extension because i have this error installing app

Apr 27 18:42:43 iPhone installd(MobileSystemServices)[2706] <Notice>: 0x16e0db000 +[MICodeSigningVerifier _validateSignatureAndCopyInfoForURL:withOptions:error:]: 147: Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.lpwIoL/extracted/Payload/JRUITouch.app/PlugIns/NotificationServiceExtension.appex : 0xe8008001 (An unknown error has occurred.)


Could you send command to execute for resigning app?
Comment 32 Rolf Bjarne Kvinge [MSFT] 2017-04-27 17:03:40 UTC
(In reply to Luigi Saggese from comment #31)
> 
> Could you send command to execute for resigning app?

Enable diagnostic build log in Xamarin Studio's preferences (Projects -> General -> Log verbosity), and the exact codesign command is printed to the build log.

This means that you can build the solution first with your Xamarin.iOS extension, get the codesign command from the build log, and then just re-execute that same command later.
Comment 33 Luigi Saggese 2017-04-28 07:15:00 UTC
Created attachment 21865 [details]
Verbosity Log
Comment 34 Luigi Saggese 2017-04-28 07:16:41 UTC
I have attached my verbosity log, but it's really difficult to understand between all command which one execute. Maybe be more clear with specific command to run it will help all users that have this issue and want to use this workaround (that as is it's it self a pain).

Thanks for your help in advance
Comment 35 Rolf Bjarne Kvinge [MSFT] 2017-04-28 07:30:51 UTC
This is the relevant line:

> Tool /usr/bin/codesign execution started with arguments: -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 --entitlements /Users/luigi.saggese/Projects/jrmobileapp/NotificationServiceExtension/obj/iPhone/Release/Entitlements.xcent /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/bin/iPhone/Ad-Hoc/JRUITouch.app/PlugIns/NotificationServiceExtension.appex

so the command would be:

> /usr/bin/codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 --entitlements /Users/luigi.saggese/Projects/jrmobileapp/NotificationServiceExtension/obj/iPhone/Release/Entitlements.xcent /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/bin/iPhone/Ad-Hoc/JRUITouch.app/PlugIns/NotificationServiceExtension.appex
Comment 36 Luigi Saggese 2017-04-28 07:43:09 UTC
This is device log when i try to install app on device

Apr 28 09:41:16 iPhone installd(MobileSystemServices)[3541] <Notice>: 0x16dfef000 +[MICodeSigningVerifier _validateSignatureAndCopyInfoForURL:withOptions:error:]: 147: Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.QBb4HH/extracted/Payload/JRUITouch.app/PlugIns/NotificationServiceExtension.appex : 0xe8008001 (An unknown error has occurred.)
Comment 37 Rolf Bjarne Kvinge [MSFT] 2017-04-28 07:48:06 UTC
I forgot to mention that you also have to codesign the app again after resigning the extension:

> /usr/bin/codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 --entitlements /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/obj/iPhone/Ad-Hoc/Entitlements.xcent /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/bin/iPhone/Ad-Hoc/JRUITouch.app

However that's not why you're still getting the code signing error.

Can you try verifying the signatures of the app and appex like this and see if something's reported?

> codesign --verify --verbose --verbose /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/bin/iPhone/Ad-Hoc/JRUITouch.app/PlugIns/NotificationServiceExtension.appex
> codesign --verify --verbose --verbose /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/bin/iPhone/Ad-Hoc/JRUITouch.app

If that doesn't give any clues, please attach the entire device log with the signing error (sometimes there are more lines that can give clues).
Comment 38 Luigi Saggese 2017-04-28 07:59:51 UTC
Those are my step:

1. I have created a Payload directory empty and put inside my JRUITouch.app (build with Xamarin Studio with configuration Ad-Hoc)
2. Open JRUITouch.app, replaced NotificationServiceExtension.appex with Obj-c version
3. Execute this commands (inside Payload directory)

➜  Payload codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 JRUITouch.app/Frameworks/IQKeyboardManager.framework/IQKeyboardManager
codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 JRUITouch.app/Frameworks/Mono.framework/Mono
codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 --entitlements /Users/luigi.saggese/Projects/jrmobileapp/NotificationServiceExtension/obj/iPhone/Release/Entitlements.xcent JRUITouch.app/PlugIns/NotificationServiceExtension.appex
codesign -v --force --sign E6F0A652CC9E9AF5C3D62AE380EED1B3D2F383A5 --entitlements /Users/luigi.saggese/Projects/jrmobileapp/JR.UI.Touch/obj/iPhone/Ad-Hoc/Entitlements.xcent JRUITouch.app
JRUITouch.app/Frameworks/IQKeyboardManager.framework/IQKeyboardManager: replacing existing signature
JRUITouch.app/Frameworks/IQKeyboardManager.framework/IQKeyboardManager: signed bundle with Mach-O universal (armv7 arm64) [org.cocoapods.IQKeyboardManager]
JRUITouch.app/Frameworks/Mono.framework/Mono: replacing existing signature
JRUITouch.app/Frameworks/Mono.framework/Mono: signed bundle with Mach-O universal (armv7 arm64) [xamarin.ios.mono-framework]
JRUITouch.app/PlugIns/NotificationServiceExtension.appex: replacing existing signature
JRUITouch.app/PlugIns/NotificationServiceExtension.appex: signed bundle [com.jobrapido.mobileapp.notificationserviceextension]
JRUITouch.app: replacing existing signature
JRUITouch.app: signed app bundle with Mach-O universal (armv7 arm64) [com.jobrapido.mobileapp]
➜  Payload codesign --verify --verbose --verbose JRUITouch.app/PlugIns/NotificationServiceExtension.appex

JRUITouch.app/PlugIns/NotificationServiceExtension.appex: valid on disk
JRUITouch.app/PlugIns/NotificationServiceExtension.appex: satisfies its Designated Requirement
➜  Payload codesign --verify --verbose --verbose JRUITouch.app
JRUITouch.app: valid on disk
JRUITouch.app: satisfies its Designated Requirement


After i compressed Payload directory (right click on directory ->Compress). Renamed as MyApp.ipa.
Xcode -> Device -> Select My Device -> + (to load an ipa)

When i select MyApp.ipa, Device log report again this:

Apr 28 09:58:21 iPhone installd(Security)[3541] <Notice>: could not enable test hierarchy: ApplePinningAllowTestCertsiPhoneApplicationSigning not true
Apr 28 09:58:21 iPhone securityd[105] <Notice>: cert[0]: SubjectCommonName =(leaf)[]> 0
Apr 28 09:58:21 iPhone securityd[105] <Notice>: cert[0]: CheckLeafMarkerOid =(leaf)[]> 0
Apr 28 09:58:21 iPhone securityd[105] <Notice>: cert[0]: IssuerCommonName =(path)[]> 0
Apr 28 09:58:21 iPhone installd(Security)[3541] <Notice>:  [leaf CheckLeafMarkerOid IssuerCommonName SubjectCommonName]
Apr 28 09:58:21 iPhone installd(libmis.dylib)[3541] <Error>: unrecognized status -67049 from codesigning library
Apr 28 09:58:21 iPhone installd(libmis.dylib)[3541] <Notice>: Could not copy code signature (error 0xe8008001).
Apr 28 09:58:21 iPhone installd(MobileSystemServices)[3541] <Notice>: 0x16dfef000 +[MICodeSigningVerifier _validateSignatureAndCopyInfoForURL:withOptions:error:]: 147: Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.Yt5Bb8/extracted/Payload/JRUITouch.app/PlugIns/NotificationServiceExtension.appex : 0xe8008001 (An unknown error has occurred.)
Apr 28 09:58:21 iPhone installd(MobileSystemServices)[3541] <Notice>: 0x16dfef000 -[MIInstaller performInstallationWithError:]: Verification stage failed
Apr 28 09:58:22 iPhone installd(MobileInstallation)[3541] <Notice>: <private>:Install (New):0:Fail:End
Apr 28 09:58:22 iPhone lsd(MobileInstallation)[79] <Notice>: _:InstallBundle:1:Fail:<private>
Apr 28 09:58:22 iPhone lsd(MobileInstallation)[79] <Notice>: _:InstallBundle:2:Success:<private>
Apr 28 09:58:22 iPhone lsd(MobileInstallation)[79] <Notice>: _:InstallBundle:5:Fail:<private>
Apr 28 09:58:22 iPhone mobile_installation_proxy(MobileInstallation)[3540] <Notice>: _:_:3:Fail:<private>
Apr 28 09:58:22 iPhone lsd(Foundation)[79] <Notice>: <NSXPCConnection: 0x1018035e0> connection from pid 3540: Warning: Exception caught during decoding of received message, dropping incoming message.
Exception: Exception while decoding argument 0 (#2 of invocation):
<NSInvocation: 0x101848480>
return value: {v} void
target: {@} 0x0
selector: {:} sendFailedNotificationForApp:isUninstall:
argument 2: {@} 0x0
argument 3: {B} 0 ''

Exception: Impossibile leggere i dati perch\M-C\M-) non sono presenti.
Apr 28 09:58:22 iPhone mobile_installation_proxy(MobileInstallation)[3540] <Notice>: _:LSInstallNotifications:1:Success:<private>
Apr 28 09:58:22 iPhone mobile_installation_proxy(MobileInstallation)[3540] <Notice>: _:_:4:Success:<private>
Apr 28 09:58:22 iPhone mobile_installation_proxy(MobileSystemServices)[3540] <Notice>: 0x16defb000 handle_install: Installation failed: Error Domain=MIInstallerErrorDomain Code=13 "Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.Yt5Bb8/extracted/Payload/JRUITouch.app/PlugIns/NotificationServiceExtension.appex : 0xe8008001 (An unknown error has occurred.)" UserInfo={NSLocalizedDescription=Failed to verify code signature of /private/var/installd/Library/Caches/com.apple.mobile.installd.staging/temp.Yt5Bb8/extracted/Payload/JRUITouch.app/PlugIns/NotificationServiceExtension.appex : 0xe8008001 (An unknown error has occurred.), LegacyErrorString=ApplicationVerificationFailed, SourceFileLine=147, LibMISErrorNumber=-402620415, FunctionName=+[MICodeSigningVerifier _validateSignatureAndCopyInfoForURL:withOptions:error:]}
Apr 28 09:58:22 iPhone mobile_installation_proxy(MobileCoreServices)[3540] <Notice>: interruptionHandler called, re-establishing connection to lsd
Apr 28 09:58:22 iPhone securityd[105] <Notice>: cert[0]: NonEmptySubject =(leaf)[]> 0
Apr 28 09:58:22 iPhone securityd[105] <Notice>: cert[0]: AnchorTrusted =(leaf)[force]> 0
Apr 28 09:58:22 iPhone CommCenter(libATCommandStudioDynamic.dylib)[74] <Notice>: QMI: Svc=0x22(COEX) Ind MsgId=0x0021 Bin=[<private>]
Apr 28 09:58:23 iPhone DuetHeuristic-BM(DuetActivitySchedulerDaemon)[124] <Notice>: Attempting to suspend based on triggers: <private>
Apr 28 09:58:23 iPhone DuetHeuristic-BM(DuetActivitySchedulerDaemon)[124] <Notice>: Evaluating 123 activities based on triggers
Comment 39 Rolf Bjarne Kvinge [MSFT] 2017-04-28 08:10:49 UTC
Can you zip up and attach both your original NotificationServiceExtension.appex directory and the one created by Xcode?
Comment 40 Luigi Saggese 2017-04-28 08:24:12 UTC
Created attachment 21867 [details]
Zip with extensions

RichPushExtension.appex is made with Xcode (Obj-c)
NotificationServiceExtension.appex is made with Xamarin Studio (C#)

When i copy inside PlugIns i remove NotificationServiceExtension.appex and move-rename RichPushExtension.appex to NotificationServiceExtension.appex
Comment 41 Rolf Bjarne Kvinge [MSFT] 2017-04-28 08:38:12 UTC
In RichPushExtension.appex/Info.plist, you say the executable name is "NotificationServiceExtension1"

	<key>CFBundleExecutable</key>
	<string>NotificationServiceExtension1</string>

but the executable inside the appex is named "RichPushExtension". This might be the reason for the signing failure.

Also I would suggest "NotificationServiceExtension" (not "NotificationServiceExtension1"), so that it matches the directory name.

You're also only building the Xcode extension for arm64, while the Xamarin Studio extension you're building for both arm64 and armv7 (but this shouldn't cause signing problems).
Comment 42 Luigi Saggese 2017-04-28 09:11:18 UTC
Thanks, now I changed the reference to RichPushExtension to NotificationServiceExtension and resigned application and now the app is installed correctly.

I test rich push notification and it works.
I hope that is a short temporary workaround because it's not really easy for all Xamarin developers do it (also for me :-P).
Comment 43 Rolf Bjarne Kvinge [MSFT] 2017-04-28 09:36:58 UTC
Good to hear you made it work :) I also hope to be able to fix it soon.
Comment 44 Luigi Saggese 2017-04-28 09:40:06 UTC
@Rolf, I'm testing to use Link All Behavior and LLVM optimizing compiler to understand if *.appex reduce its size (but for the moment there are no differences into output size). Because main difference between Obj-C appex and C# it's about their sizes.

OBJ-c appex is around 100Kb
C# appex is around 6.6MB
Comment 45 Rolf Bjarne Kvinge [MSFT] 2017-04-28 09:42:29 UTC
appex size is something we've improved a lot on for the next release: https://developer.xamarin.com/releases/ios/xamarin.ios_10/xamarin.ios_10.10/#Code_sharing_between_Applications_and_Extensions

You can try it out if you switch to the Beta channel.
Comment 46 Luigi Saggese 2017-04-28 09:44:41 UTC
I'm already in Beta channel, I must change something how my project reference app extension?
Comment 47 Rolf Bjarne Kvinge [MSFT] 2017-04-28 10:04:49 UTC
Your build settings must be identical between the projects:

> /Users/luigi.saggese/Projects/jrmobileapp/packages/SQLitePCL.raw_basic.0.8.6/build/Xamarin.iOS10/pinvoke_sqlite3/anycpu/SQLitePCL.raw.dll, actual path: /Users/luigi.saggese/Projects/jrmobileapp/packages/SQLitePCL.raw.0.9.2/lib/Xamarin.iOS10/SQLitePCL.raw.dll).
>	MTOUCH:  warning MT0113: Native code sharing has been disabled for the extension 'NotificationServiceExtension' because the managed linker settings are different between the container app (All) and the extension (SDKOnly).
Comment 48 Luigi Saggese 2017-04-28 10:32:45 UTC
Ah perfect! 
Now with same build settings *.appex is 2.3MB but when i test rich push notification (now with extension in C#) it do not display image with same error reported in the past.

Info (118) / symptomsd(SymptomEvaluator): Entry, display name com.jobrapido.mobileapp.notificationserviceextension uuid BEE0E6F0-3E03-3F71-A2F9-CB456F8B4BBD pid 3778 isFront 1
Info (118) / symptomsd(SymptomEvaluator): Check for bundle name com.jobrapido.mobileapp returns 0
Info (118) / symptomsd(SymptomEvaluator): app name com.jobrapido.mobileapp isForeground 1  hasForegroundApps 1, current idea of foreground 0 disp (null)
Info (118) / symptomsd(SymptomEvaluator): Going to Foreground, new flags 0x8028000, initial value 0x8028000, enabled 0
Info (118) / symptomsd(SymptomEvaluator): Continue with bundle name com.jobrapido.mobileapp, is front 1
Info (118) / symptomsd(SymptomEvaluator): com.jobrapido.mobileapp: Foreground: true
Info (118) / symptomsd(SymptomEvaluator): Set appCompactState object 958534 for key com.jobrapido.mobileapp
Info (118) / symptomsd(SymptomEvaluator): CFSM2 foreground (current/proposed/state) in = (1/1/3)
Info (118) / symptomsd(SymptomEvaluator): CFSM2 foreground (current/state) out = (1/1)
Info (53) / SpringBoard(PlugInKit): connection to plug-in <private>(4D715DBD-347E-4EA4-AF8F-64D0A6ED1590) lost
Info (53) / SpringBoard(PlugInKit): connection to plug-in <private>(<private>) lost
Error (53) / SpringBoard(UserNotificationsServer): Extension error whilst trying to modify push notification EC21-FDB4: Error Domain=NSCocoaErrorDomain Code=4097 "connection from pid 3778" UserInfo={NSDebugDescription=connection from pid 3778}
Info (53) / SpringBoard(UserNotificationsServer): [com.jobrapido.mobileapp] Saving notification EC21-FDB4
Error (53) / SpringBoard(UserNotificationsServer): Could not load data at /var/mobile/Library/SpringBoard/PushStore/com.jobrapido.mobileapp.pushstore
Info (53) / SpringBoard(UserNotificationsServer): Saving notification list at /var/mobile/Library/SpringBoard/PushStore/com.jobrapido.mobileapp.pushstore with 1 items
Comment 49 Rolf Bjarne Kvinge [MSFT] 2017-04-28 10:35:03 UTC
The physical size on disk does not reflect the memory usage at runtime. What we've reduced in the upcoming release is the physical size on disk, not the memory usage.
Comment 50 Luigi Saggese 2017-04-28 12:11:58 UTC
Ah ok. 
When there are some update on this fix let me know that i will test for you.

Thanks for support.
Comment 51 Luigi Saggese 2017-05-24 11:31:25 UTC Comment hidden (obsolete)
Comment 52 Luigi Saggese 2017-05-24 12:04:07 UTC Comment hidden (obsolete)
Comment 53 Luigi Saggese 2017-05-24 13:04:52 UTC Comment hidden (obsolete)
Comment 54 Rolf Bjarne Kvinge [MSFT] 2017-05-24 14:33:59 UTC Comment hidden (obsolete)
Comment 55 Luigi Saggese 2017-07-13 14:22:23 UTC
Some news on this bug?
Comment 56 Rolf Bjarne Kvinge [MSFT] 2017-07-13 14:42:17 UTC
@Luigi, unfortunately more important tasks keep interfering, and I'm not sure when I'll get the time to fix it.
Comment 57 Bob 2017-07-19 17:14:59 UTC
Rolf...can you provide any ETA.  Understand you are busy, but this is a basic feature on the iOS platform that has been avail for some time.  Clients are asking why we are even bothering with Xamarin if they can't even address core functionality issues.  Am concerned about message this sends to community.

-bob
Comment 58 jellis 2017-07-28 02:34:27 UTC
+1 also affecting our app - just have a single line like this for image attachment download:

var imageData = NSData.FromUrl(logoUrl);

The image file is around 5KB. On most devices, it works approx 80% of time, but intermittently fails, assuming memory limit.  on some devices it doesn't work at all.  Have stripped down the rest of the code to the bare minimum, no other libraries included, all compiler optimizations on.
Comment 59 Dave Barnes 2017-07-28 08:56:33 UTC
Another +1 here. My service extension is working fine, but is failing when I try to do the image download.
Comment 60 Mikalai Daronin 2017-07-28 09:10:55 UTC
I suppose it may be very difficult (impossible?) to fix this issue; in that case I would prefer to have a convenient way to include native (ObjC/Swift) extensions to a Xamarin app. I followed this answer (http://stackoverflow.com/a/43647608/183422) in order to use a native extension and everything works, but now my csproj looks like Frankenstein.
Comment 61 Rolf Bjarne Kvinge [MSFT] 2017-08-07 11:31:36 UTC
*** Bug 58566 has been marked as a duplicate of this bug. ***
Comment 62 Rolf Bjarne Kvinge [MSFT] 2017-08-09 15:06:51 UTC
(In reply to Bob from comment #57)
> Rolf...can you provide any ETA.  Understand you are busy, but this is a
> basic feature on the iOS platform that has been avail for some time. 

I'm sorry, but unfortunately I can't provide any ETA.

I completely understand your concerns, but at the moment we're working on other areas that are more urgent.
Comment 63 xamarinbugzilla 2017-09-09 04:43:38 UTC
I'd like to add on a "me-too" here. Rich Push is becoming more desired by clients. I can't even open a socket in there without blowing out the memory limit. The MonkeyHandler demo in the documentation website (that downloads images in push extension) seems to me it could never work. It's pseudo code anyways. Someone should flag that or something so people don't waste HOURS AND HOURS on something that cannot possibly work.
Comment 64 clintoncraigsmith 2017-10-03 18:55:09 UTC
+1 for needing this addressed:

Has there been any triage to scope the effort this would take after addressing the dependency 56022?
Comment 65 Rolf Bjarne Kvinge [MSFT] 2017-10-06 07:43:14 UTC
(In reply to clintoncraigsmith from comment #64)
> +1 for needing this addressed:
> 
> Has there been any triage to scope the effort this would take after
> addressing the dependency 56022?

What needs to be done is fairly simple to explain: Xamarin.iOS' memory overhead needs to be lowered.

Fixing bug #56022 will reduce Xamarin.iOS' memory overhead (but it's unclear how much before actually completing the work); if that's enough to make the scenario described in this bug work, then there's nothing more to do.

If it's not enough, then we'll have to find out what else we can do, but we won't be able to do that before bug #56022 is actually fixed.
Comment 66 tmrog 2017-11-17 18:58:04 UTC
Rolf - any chance of Xamarin producing a step-by-step write up of how to automate and incorporate an Xcode built app extension into a Xamarin project?

This might save you some time dealing with this and really help everybody out especially considering there seems to be no ETA on reducing the Xamarin memory footprint.  

Pretty please...

Ted
Comment 67 Rolf Bjarne Kvinge [MSFT] 2017-11-20 09:57:30 UTC
@tmrog, have you seen this stack overflow answer: https://stackoverflow.com/a/43647608/183422? It explains it pretty well. In any case I'll talk to the documentation team to see what we can do.
Comment 68 tmrog 2017-11-20 12:27:17 UTC
@Rolf - thank you.
Comment 69 tmrog 2017-11-20 12:30:53 UTC
@Rolf - what I meant to say was yes I have read that stack overflow article and thank you for talking with the doc team.
Comment 70 tmrog 2017-12-13 18:41:26 UTC
Hi Guys,

I was able to rebuild my FileProvider using Swift and manually copy it and the Swift Frameworks into my main app, code sign, and run with no problems.

I've been working on automating the build process today. I added a couple run scripts to Xcode to copy my FileProvider extension and Swift Frameworks to a location that I can use from within my Xamarin project.  I am having a few problems.

I have created a "BeforeCodeSign" target and it seems to do exactly the right thing when I run it with msbuild from the command line and my file provider extension looks like it should.

I added this to the bottom of my file provider extension project right before the closing project tag.

  <Target Name="BeforeCodeSign">
    <ItemGroup>
        <NativeExtensionDirectory Include="..\..\Bin\Debug-iphoneos\PDMFileProvider.appex\**\*.*" />
    </ItemGroup>

    <Message Text="Processing BeforeCodeSign" />
        
    <!-- cleanup the application extension built with Xamarin (too heavy in memory)-->
    <RemoveDir SessionId="$(BuildSessionId)"
               Directories="bin\iPhone\Debug\device-builds\ipad7.1-11.1.2\PDMFileProvider.appex"/>

    <!-- copy the native one, built in obj-c -->
    <Copy
            SessionId="$(BuildSessionId)"
            SourceFiles="@(NativeExtensionDirectory)"
            DestinationFolder="bin\iPhone\Debug\device-builds\ipad7.1-11.1.2\PDMFileProvider.appex"
            SkipUnchangedFiles="true"
            OverwriteReadOnlyFiles="true"
            Retries="3"
            RetryDelayMilliseconds="300"/>
  </Target>

Output when running msbuild from command line:

Project "/Users/trs2/Documents/TFS2/ePDM2019/MobileApps/PDMApp/FileProvider/FileProvider.csproj" on node 1 (BeforeCodeSign target(s)).
BeforeCodeSign:
  Processing BeforeCodeSign
  Removing directory "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex".
  Creating directory "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex".
  Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/embedded.mobileprovision" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/embedded.mobileprovision".
  Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/Info.plist" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/Info.plist".
  Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/PDMFileProvider" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/PDMFileProvider".
Done Building Project "/Users/trs2/Documents/TFS2/ePDM2019/MobileApps/PDMApp/FileProvider/FileProvider.csproj" (BeforeCodeSign target(s)).


 However, when I build my app project it does not seem to work.  When I do a clean all and hit run the build log appears like it did all the right thing but in the end I end up with my Xamarin File Provider.  Here is the build log output excerpt:

Target "BeforeCodeSign" in file "/Users/trs2/Documents/TFS2/ePDM2019/MobileApps/PDMApp/FileProvider/FileProvider.csproj":
  Added Item(s): 
      NativeExtensionDirectory=
          ../../Bin/Debug-iphoneos/PDMFileProvider.appex/embedded.mobileprovision
          ../../Bin/Debug-iphoneos/PDMFileProvider.appex/Info.plist
          ../../Bin/Debug-iphoneos/PDMFileProvider.appex/PDMFileProvider
  Task "Message"
    Task Parameter:Text=Processing BeforeCodeSign
    Processing BeforeCodeSign
  Done executing task "Message".
  Task "RemoveDir"
    Task Parameter:Directories=bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex
    Removing directory "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex".
  Done executing task "RemoveDir".
  Task "Copy"
    Task Parameter:
        SourceFiles=
            ../../Bin/Debug-iphoneos/PDMFileProvider.appex/embedded.mobileprovision
            ../../Bin/Debug-iphoneos/PDMFileProvider.appex/Info.plist
            ../../Bin/Debug-iphoneos/PDMFileProvider.appex/PDMFileProvider
    Task Parameter:DestinationFolder=bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex
    Task Parameter:SkipUnchangedFiles=True
    Task Parameter:OverwriteReadOnlyFiles=True
    Task Parameter:Retries=3
    Task Parameter:RetryDelayMilliseconds=300
    Creating directory "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex".
    Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/embedded.mobileprovision" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/embedded.mobileprovision".
    Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/Info.plist" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/Info.plist".
    Copying file from "../../Bin/Debug-iphoneos/PDMFileProvider.appex/PDMFileProvider" to "bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/PDMFileProvider".
  Done executing task "Copy".
Done building target "BeforeCodeSign" in project "FileProvider.csproj".

I feel like maybe there is something else I need to do but just don't know what.  Also, I would like to replace the hard-coded path components used in my "BeforeCodeSign" target with symbols wherever I can but was not able to find the correct symbols.
Comment 71 tmrog 2017-12-13 20:00:43 UTC
I think my problem is contained in the build log excerpt below.  If I build my FileProvider on its own, the appex looks good.  Once I go to build the host app, the FileProvider gets rebuilt as part of that process.

Anybody know how I should go about fixing it?  

	Target _CompileToNative needs to be built as input file '/Users/trs2/Documents/TFS2/ePDM2019/MobileApps/PDMApp/FileProvider/bin/iPhone/Debug/PDMFileProvider.dll' is newer than output file 'bin/iPhone/Debug/device-builds/ipad7.1-11.1.2/PDMFileProvider.appex/PDMFileProvider'
Comment 72 Mikalai Daronin 2017-12-13 20:13:54 UTC
>I added this to the bottom of my file provider extension project right before the closing project tag.

Hm, why you added the "BeforeCodeSign" to the extension project? I think you should move it into the main app csproj. As far I know IDE can skip building project dependencies if they are already built.

In our app we have added very similar tasks to the main csproj and now everything works fine from command-line MSBuild and in the VS for Mac.
Comment 73 tmrog 2017-12-13 20:40:13 UTC
I was following the instructions from above.  The issue is that when the files are copied, the dates are not updated.  Since my extension was built earlier in the day in XCode, it always gets rebuilt.  I tried manually touching it and it still rebuilt it.  Still investigating that.  

This is from the SO article referenced above:

"Or you can automate this process, to to so, place the appex file in the csproj's extension and set the build-action as "content". Then in this csproj's file (you'll need to edit directly) you can add something like this. (In this case, the file is called Notifications.appex and is placed in a folder called NativeExtension)"
Comment 74 tmrog 2017-12-13 20:50:49 UTC
@Nikolai Doronim I was hoping by doing it in the extensions BeforeCodeSign I would not have to do any additional code signing steps.  How does that get handled if you copy the extension over in the main app BeforeCodeSign?
Comment 75 Mat 2017-12-13 20:52:58 UTC
The SO answer is doing those steps:
1- manually build a appex in xcode, using the same bundle ID and same signature as you would in visual studio for your xamarin appex.
2- Place that appex in your visual studio solution as Content.
3- in the main app csproj, in BeforeCodeSign, take that native appex and replace the xamarin-built one. 

Only step 3 is automated by the SO answer I wrote.
Comment 76 Bob 2018-02-10 22:37:43 UTC
Any update on when this will be fixed in Xamarin.
Comment 77 Rolf Bjarne Kvinge [MSFT] 2018-02-12 08:56:28 UTC
@Bob, I'm working on it, but I have no dates yet.
Comment 78 Rolf Bjarne Kvinge [MSFT] 2018-03-08 13:34:52 UTC
Looks like this is working with the fix for #56022.

I can successfully modify notifications using the project from the initial description (it even works in debug mode, although putting a breakpoint and stepping through the code makes the extension hit the memory limit and it's killed).

This will be released in our next stable release (d15-7). Previews should be available in the alpha or beta channel fairly soon.
Comment 79 Bob 2018-03-08 14:16:12 UTC
Rolf..Thanks for the update!
Comment 80 Shawn Castrianni 2018-03-19 20:03:38 UTC
Rolf, I have a similar issue, but do not mess with images.  I am simply trying to aggregate notifications into 1.  This works fine on iOS11, but not on iOS10.  Below is the log for iOS10.  I just get an error message with "connection from pid 369".  Not very useful.  My extension source is also below.  I am not doing anything fancy.  Any ideas?


        public async override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        {
            ContentHandler = contentHandler;
            _origNotification = request.Content;
            UNUserNotificationCenter nc = UNUserNotificationCenter.Current;
            //Find most recent notification article count
            int pendingNumArticles = 0;
            UNNotification[] dns = await nc.GetDeliveredNotificationsAsync();
            UNNotification mostRecent = dns.OrderByDescending(n => n.Date).FirstOrDefault();
            NSString numArticlesKey = new NSString(NUM_ARTICLES);
            if((mostRecent != null) && (mostRecent.Request.Content.UserInfo.ContainsKey(numArticlesKey)))
                pendingNumArticles = ((NSNumber)mostRecent.Request.Content.UserInfo.ObjectForKey(numArticlesKey)).Int32Value;
			//Remove all previous notifications
			nc.RemoveAllDeliveredNotifications();
			//Find article count from this notification
			int newNumArticles = 0;
			if (request.Content.UserInfo.ContainsKey(numArticlesKey))
				newNumArticles = ((NSNumber)request.Content.UserInfo.ObjectForKey(numArticlesKey)).Int32Value;
            int aggregatedNumArticles = pendingNumArticles + newNumArticles;
            //If aggregation count is just 1, then display notification as is
            if (aggregatedNumArticles == 1)
                ContentHandler(_origNotification);
            else {
                //Copy this notification to modify it
                UNMutableNotificationContent aggregatedNotification = (UNMutableNotificationContent)_origNotification.MutableCopy();
                aggregatedNotification.Title = string.Empty;
                aggregatedNotification.Body = "" + aggregatedNumArticles + " new articles published";
                aggregatedNotification.Badge = NSNumber.FromInt32(aggregatedNumArticles);
                NSMutableDictionary aggregatedUserInfo = (NSMutableDictionary)_origNotification.UserInfo.MutableCopy();
                aggregatedUserInfo[numArticlesKey] = aggregatedNotification.Badge;
                aggregatedNotification.UserInfo = aggregatedUserInfo;
                ContentHandler(aggregatedNotification);
            }
        }




Mar 19 14:22:51 Gregorys-iPhone-5S assertiond[61] <Notice>: Ignoring assertion request named "com.apple.extension.session" from <BSProcessHandle: 0x11fd0ad90; SpringBoard:51; valid: YES> because process { pid 365; bundleID (null) } is unknown.
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: calling plugIn beginUsing:
Mar 19 14:22:51 Gregorys-iPhone-5S pkd[145] <Notice>: allowing host 51 /System/Library/CoreServices/SpringBoard.app/SpringBoard to use plug-in <private>(<private>) uuid=32CFA519-4F0C-4F77-9BC3-FCD8B34D446F at <private>
Mar 19 14:22:51 Gregorys-iPhone-5S NotificationAggregation.iOS(Mono)[369] <Notice>: Found new TLS offset at 224
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: completed calling plugIn beginUsing: for pid: 369
Mar 19 14:22:51 Gregorys-iPhone-5S NotificationAggregation.iOS(Foundation)[369] <Notice>: in _willPerformHostCallback: block
Mar 19 14:22:51 Gregorys-iPhone-5S mediaserverd(CoreMedia)[25] <Notice>: -CMSessionMgr- cmsmHandleApplicationStateChange: CMSession: Client com.ihs.energyalert.notifications with pid '369' is now Foreground Running. Background entitlement: NO
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: 369 com.ihs.energyalert.notifications: ForegroundRunning (most elevated: ForegroundRunning)
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: Entry, display name com.ihs.energyalert.notifications uuid 3CD26EDB-0C78-3A08-9C96-8800462A45A8 pid 369 isFront 1
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: Check for bundle name com.ihs.energyalert returns 0
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: app name com.ihs.energyalert isForeground 1  hasForegroundApps 1, current idea of foreground 0 disp (null)
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: Going to Foreground, new flags 0x0, initial value 0x0, enabled 0
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: Continue with bundle name com.ihs.energyalert, is front 1
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: com.ihs.energyalert: Foreground: true
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: Set appCompactState object 1758576 for key com.ihs.energyalert
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: CFSM2 foreground (current/proposed/state) in = (0/1/2)
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: CFSM2 foreground (current/state) out = (1/1)
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: CFSM Current state: idle, changed: systemForeground to 1 for net type 0, eligible for alerted but constraints unsatisfied (1,0,0,0)
Mar 19 14:22:51 Gregorys-iPhone-5S CommCenter[73] <Notice>: #I BundleID: <private> is a foreground app
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: CFSM Current state: idle, changed: systemForeground to 1 for net type 0, ineligible for committed as nil pred, wifi (0x0) cell (0x0)
Mar 19 14:22:51 Gregorys-iPhone-5S symptomsd(SymptomEvaluator)[124] <Notice>: CFSM Relays: cell (active-no/primary-no/knowngood-no/rssithresh-ok/txthresh-ok/arp-ok/dns-ok/tcp-ok/lqm:-2/advisory:0) wifi (active/primary/knowngood/rssithresh-ok/txthresh-ok/arp-ok/dns-ok/tcp-ok/lqm:100/advisory:7)
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(PlugInKit)[51] <Notice>: connection to plug-in <private>(32CFA519-4F0C-4F77-9BC3-FCD8B34D446F) lost
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(PlugInKit)[51] <Notice>: connection to plug-in <private>(<private>) lost
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: tearing down extension request for pid 0
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Error>: Extension error whilst trying to modify push notification 5AAD-379D: Error Domain=NSCocoaErrorDomain Code=4097 "connection from pid 369" UserInfo={NSDebugDescription=connection from pid 369}
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: extension connection was interrupted
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Notice>: UNSUserNotificationServerConnectionListener connection invalidated
Mar 19 14:22:51 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Notice>: [com.ihs.energyalert] Saving notification 5AAD-379D
Comment 81 Shawn Castrianni 2018-03-19 22:49:35 UTC
Since there is no way to debug an extension (that I know of), I added Console.Writeline messages to my extension since those show up in the device log.  I put a writeline before every single line of code in my extension, like below.  The device log output showed the below. Notice that it printed out line number 7 but did not print out 8.  That means it died on this line:

NSString numArticlesKey = new NSString(NUM_ARTICLES);

where:

private const string NUM_ARTICLES = "numArticles";

any ideas?


Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 1
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 2
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 3
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 4
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 5
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 6
Mar 19 17:31:27 Gregorys-iPhone-5S NotificationAggregation.iOS(Xamarin)[449] <Notice>: NotificationService: 7
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(PlugInKit)[51] <Notice>: connection to plug-in <private>(C7051547-5FE3-4616-AB09-6CC4A94EB730) lost
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(PlugInKit)[51] <Notice>: connection to plug-in <private>(<private>) lost
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: extension connection was interrupted
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Error>: Extension error whilst trying to modify push notification E4C6-7201: Error Domain=NSCocoaErrorDomain Code=4097 "connection from pid 449" UserInfo={NSDebugDescription=connection from pid 449}
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(Foundation)[51] <Notice>: tearing down extension request for pid 0
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Notice>: [com.ihs.energyalert] Saving notification E4C6-7201
Mar 19 17:31:27 Gregorys-iPhone-5S SpringBoard(UserNotificationsServer)[51] <Notice>: Saving notification list at /var/mobile/Library/SpringBoard/PushStore/com.ihs.energyalert.pushstore with 2 items
Mar 19 17:31:27 Gregorys-iPhone-5S mediaserverd(CoreMedia)[25] <Notice>: -CMSessionMgr- cmsmHandleApplicationStateChange: CMSession: Client com.ihs.energyalert.notifications with pid '449' is now Background Suspended. Background entitlement: NO




        public async override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        {
            Console.WriteLine("NotificationService: 1");
            ContentHandler = contentHandler;
            Console.WriteLine("NotificationService: 2");
            _origNotification = request.Content;
            Console.WriteLine("NotificationService: 3");
            UNUserNotificationCenter nc = UNUserNotificationCenter.Current;
            //Find most recent notification article count
            Console.WriteLine("NotificationService: 4");
            int pendingNumArticles = 0;
            Console.WriteLine("NotificationService: 5");
            UNNotification[] dns = await nc.GetDeliveredNotificationsAsync();
            Console.WriteLine("NotificationService: 6");
            UNNotification mostRecent = dns.OrderByDescending(n => n.Date).FirstOrDefault();
            Console.WriteLine("NotificationService: 7");
            NSString numArticlesKey = new NSString(NUM_ARTICLES);
            Console.WriteLine("NotificationService: 8");
            if ((mostRecent != null) && (mostRecent.Request.Content.UserInfo.ContainsKey(numArticlesKey))) {
                Console.WriteLine("NotificationService: 9");
                pendingNumArticles = ((NSNumber)mostRecent.Request.Content.UserInfo.ObjectForKey(numArticlesKey)).Int32Value;
            }
			//Remove all previous notifications
            Console.WriteLine("NotificationService: 10");
			nc.RemoveAllDeliveredNotifications();
			//Find article count from this notification
            Console.WriteLine("NotificationService: 11");
			int newNumArticles = 0;
            Console.WriteLine("NotificationService: 12");
            if (request.Content.UserInfo.ContainsKey(numArticlesKey)) {
                Console.WriteLine("NotificationService: 13");
                newNumArticles = ((NSNumber)request.Content.UserInfo.ObjectForKey(numArticlesKey)).Int32Value;
            }
            Console.WriteLine("NotificationService: 14");
            int aggregatedNumArticles = pendingNumArticles + newNumArticles;
            //If aggregation count is just 1, then display notification as is
            Console.WriteLine("NotificationService: 15");
            if (aggregatedNumArticles == 1) {
                Console.WriteLine("NotificationService: 16");
                ContentHandler(_origNotification);
            } else {
                //Copy this notification to modify it
                Console.WriteLine("NotificationService: 17");
                UNMutableNotificationContent aggregatedNotification = (UNMutableNotificationContent)_origNotification.MutableCopy();
                Console.WriteLine("NotificationService: 18");
                aggregatedNotification.Title = string.Empty;
                Console.WriteLine("NotificationService: 19");
                aggregatedNotification.Body = "" + aggregatedNumArticles + " new articles published";
                Console.WriteLine("NotificationService: 20");
                aggregatedNotification.Badge = NSNumber.FromInt32(aggregatedNumArticles);
                Console.WriteLine("NotificationService: 21");
                NSMutableDictionary aggregatedUserInfo = (NSMutableDictionary)_origNotification.UserInfo.MutableCopy();
                Console.WriteLine("NotificationService: 22");
                aggregatedUserInfo[numArticlesKey] = aggregatedNotification.Badge;
                Console.WriteLine("NotificationService: 23");
                aggregatedNotification.UserInfo = aggregatedUserInfo;
                Console.WriteLine("NotificationService: 24");
                ContentHandler(aggregatedNotification);
                Console.WriteLine("NotificationService: 25");
            }
        }