├── .gitignore
├── Core
├── App.cs
├── BackgroundPage.xaml
├── BackgroundPage.xaml.cs
├── DownloadPage.xaml
├── DownloadPage.xaml.cs
├── FormsBackgrounding.csproj
├── LongRunningPage.xaml
├── LongRunningPage.xaml.cs
├── Messages
│ ├── CancelledMessage.cs
│ ├── DownloadFinishedMessage.cs
│ ├── DownloadMessage.cs
│ ├── DownloadProgressMessage.cs
│ ├── StartLongRunningTaskMessage.cs
│ ├── StopLongRunningTaskMessage.cs
│ └── TickedMessage.cs
├── Properties
│ └── AssemblyInfo.cs
├── TaskCounter.cs
└── packages.config
├── Droid
├── Assets
│ └── AboutAssets.txt
├── FormsBackgrounding.Droid.csproj
├── ImageHelper.cs
├── MainActivity.cs
├── Properties
│ ├── AndroidManifest.xml
│ └── AssemblyInfo.cs
├── Resources
│ ├── AboutResources.txt
│ ├── Resource.designer.cs
│ ├── drawable-hdpi
│ │ └── icon.png
│ ├── drawable-xhdpi
│ │ └── icon.png
│ ├── drawable-xxhdpi
│ │ └── icon.png
│ └── drawable
│ │ └── icon.png
├── Services
│ ├── DownloaderService.cs
│ └── LongRunningTaskService.cs
└── packages.config
├── FormsBackgrounding.sln
├── XamarinFormsBackgrounding.zip
└── iOS
├── AppDelegate.cs
├── Entitlements.plist
├── FormsBackgrounding.iOS.csproj
├── ITunesArtwork
├── ITunesArtwork@2x
├── Info.plist
├── Main.cs
├── Resources
├── Default-568h@2x.png
├── Default-Portrait.png
├── Default-Portrait@2x.png
├── Default.png
├── Default@2x.png
├── Icon-60@2x.png
├── Icon-60@3x.png
├── Icon-76.png
├── Icon-76@2x.png
├── Icon-Small-40.png
├── Icon-Small-40@2x.png
├── Icon-Small-40@3x.png
├── Icon-Small.png
├── Icon-Small@2x.png
├── Icon-Small@3x.png
└── LaunchScreen.storyboard
├── Services
├── CustomSessionDownloadDelegate.cs
├── Downloader.cs
└── iOSLongRunningTaskExample.cs
└── packages.config
/.gitignore:
--------------------------------------------------------------------------------
1 | #Autosave files
2 | *~
3 |
4 | #build
5 | [Oo]bj/
6 | [Bb]in/
7 | packages/
8 | TestResults/
9 |
10 | # globs
11 | Makefile.in
12 | *.DS_Store
13 | *.sln.cache
14 | *.suo
15 | *.cache
16 | *.pidb
17 | *.userprefs
18 | *.usertasks
19 | config.log
20 | config.make
21 | config.status
22 | aclocal.m4
23 | install-sh
24 | autom4te.cache/
25 | *.user
26 | *.tar.gz
27 | tarballs/
28 | test-results/
29 | Thumbs.db
30 |
31 | #Mac bundle stuff
32 | *.dmg
33 | *.app
34 |
35 | #resharper
36 | *_Resharper.*
37 | *.Resharper
38 |
39 | #dotCover
40 | *.dotCover
41 |
--------------------------------------------------------------------------------
/Core/App.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 | using System;
3 |
4 | namespace FormsBackgrounding
5 | {
6 | public class App : Application
7 | {
8 | #region Constructor
9 | private readonly BackgroundPage _backgroundPage;
10 |
11 | public App ()
12 | {
13 | _backgroundPage = new BackgroundPage ();
14 |
15 | var tabbedPage = new TabbedPage ();
16 | tabbedPage.Children.Add (_backgroundPage);
17 | tabbedPage.Children.Add (new LongRunningPage ());
18 | tabbedPage.Children.Add (new DownloadPage ());
19 |
20 | MainPage = tabbedPage;
21 | }
22 | #endregion
23 |
24 | protected override void OnStart ()
25 | {
26 | LoadPersistedValues ();
27 | }
28 |
29 | protected override void OnSleep ()
30 | {
31 | Application.Current.Properties ["SleepDate"] = DateTime.Now.ToString("O");
32 | Application.Current.Properties ["FirstName"] = _backgroundPage.FirstName;
33 | }
34 |
35 | protected override void OnResume ()
36 | {
37 | LoadPersistedValues ();
38 | }
39 |
40 | private void LoadPersistedValues()
41 | {
42 | if (Application.Current.Properties.ContainsKey("SleepDate")) {
43 | var value = (string)Application.Current.Properties ["SleepDate"];
44 | DateTime sleepDate;
45 | if (DateTime.TryParse (value, out sleepDate)) {
46 | _backgroundPage.SleepDate = sleepDate;
47 | }
48 | }
49 |
50 | if (Application.Current.Properties.ContainsKey("FirstName")) {
51 | var firstName = (string)Application.Current.Properties ["FirstName"];
52 | _backgroundPage.FirstName = firstName;
53 | }
54 | }
55 |
56 | }
57 | }
--------------------------------------------------------------------------------
/Core/BackgroundPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Core/BackgroundPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using FormsBackgrounding.Messages;
4 |
5 | namespace FormsBackgrounding
6 | {
7 | public partial class BackgroundPage : ContentPage
8 | {
9 | public BackgroundPage ()
10 | {
11 | InitializeComponent ();
12 | }
13 |
14 | public DateTime SleepDate
15 | {
16 | set {
17 | this.SleepDateLabel.Text = value.ToString ("t");
18 | }
19 | }
20 |
21 | public string FirstName
22 | {
23 | get {
24 | return this.FirstNameEntry.Text;
25 | }
26 | set {
27 | this.FirstNameEntry.Text = value;
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Core/DownloadPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Core/DownloadPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Xamarin.Forms;
3 | using FormsBackgrounding.Messages;
4 |
5 | namespace FormsBackgrounding
6 | {
7 | public partial class DownloadPage : ContentPage
8 | {
9 | public DownloadPage ()
10 | {
11 | InitializeComponent ();
12 |
13 | downloadButton.Clicked += Download;
14 |
15 | MessagingCenter.Subscribe (this, "DownloadProgressMessage", message => {
16 | Device.BeginInvokeOnMainThread(() => {
17 | this.downloadStatus.Text = message.Percentage.ToString("P2");
18 | });
19 | });
20 |
21 | MessagingCenter.Subscribe (this, "DownloadFinishedMessage", message => {
22 | Device.BeginInvokeOnMainThread(() =>
23 | {
24 | catImage.Source = FileImageSource.FromFile(message.FilePath);
25 | });
26 | });
27 |
28 | }
29 |
30 | void Download (object sender, EventArgs e)
31 | {
32 | this.catImage.Source = null;
33 | var message = new DownloadMessage {
34 | Url = "http://xamarinuniversity.blob.core.windows.net/ios210/huge_monkey.png"
35 | };
36 |
37 | MessagingCenter.Send (message, "Download");
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Core/FormsBackgrounding.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
7 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}
8 | Library
9 | FormsBackgrounding
10 | FormsBackgrounding
11 | v4.5
12 | Profile78
13 |
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug
21 | DEBUG;
22 | prompt
23 | 4
24 | false
25 |
26 |
27 | full
28 | true
29 | bin\Release
30 | prompt
31 | 4
32 | false
33 |
34 |
35 |
36 |
37 |
38 | BackgroundPage.xaml
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | LongRunningPage.xaml
48 |
49 |
50 | DownloadPage.xaml
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | MSBuild:UpdateDesignTimeXaml
62 |
63 |
64 | MSBuild:UpdateDesignTimeXaml
65 |
66 |
67 | MSBuild:UpdateDesignTimeXaml
68 |
69 |
70 |
71 |
72 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Core.dll
73 |
74 |
75 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Xaml.dll
76 |
77 |
78 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\Xamarin.Forms.Platform.dll
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/Core/LongRunningPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Core/LongRunningPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 | using FormsBackgrounding.Messages;
3 |
4 | namespace FormsBackgrounding
5 | {
6 | public partial class LongRunningPage : ContentPage
7 | {
8 | public LongRunningPage ()
9 | {
10 | InitializeComponent ();
11 |
12 | //Wire up XAML buttons
13 | longRunningTask.Clicked += (s, e) => {
14 | var message = new StartLongRunningTaskMessage ();
15 | MessagingCenter.Send (message, "StartLongRunningTaskMessage");
16 | };
17 |
18 | stopLongRunningTask.Clicked += (s, e) => {
19 | var message = new StopLongRunningTaskMessage ();
20 | MessagingCenter.Send (message, "StopLongRunningTaskMessage");
21 | };
22 |
23 | HandleReceivedMessages ();
24 | }
25 |
26 |
27 | void HandleReceivedMessages ()
28 | {
29 | MessagingCenter.Subscribe (this, "TickedMessage", message => {
30 | Device.BeginInvokeOnMainThread(() => {
31 | ticker.Text = message.Message;
32 | });
33 | });
34 |
35 | MessagingCenter.Subscribe (this, "CancelledMessage", message => {
36 | Device.BeginInvokeOnMainThread(() => {
37 | ticker.Text = "Cancelled";
38 | });
39 | });
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/Core/Messages/CancelledMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class CancelledMessage
4 | {
5 | }
6 |
7 | }
--------------------------------------------------------------------------------
/Core/Messages/DownloadFinishedMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class DownloadFinishedMessage
4 | {
5 | public string Url { get; set; }
6 |
7 | public string FilePath { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/Core/Messages/DownloadMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class DownloadMessage
4 | {
5 | public string Url { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Core/Messages/DownloadProgressMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class DownloadProgressMessage
4 | {
5 | public long BytesWritten { get; set; }
6 |
7 | public long TotalBytesWritten { get; set; }
8 |
9 | public long TotalBytesExpectedToWrite { get; set; }
10 |
11 | public float Percentage { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Core/Messages/StartLongRunningTaskMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class StartLongRunningTaskMessage
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/Core/Messages/StopLongRunningTaskMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class StopLongRunningTaskMessage
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/Core/Messages/TickedMessage.cs:
--------------------------------------------------------------------------------
1 | namespace FormsBackgrounding.Messages
2 | {
3 | public class TickedMessage
4 | {
5 | public string Message { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 |
4 | // Information about this assembly is defined by the following attributes.
5 | // Change them to the values specific to your project.
6 |
7 | [assembly: AssemblyTitle ("FormsBackgrounding")]
8 | [assembly: AssemblyDescription ("")]
9 | [assembly: AssemblyConfiguration ("")]
10 | [assembly: AssemblyCompany ("Artek Software")]
11 | [assembly: AssemblyProduct ("")]
12 | [assembly: AssemblyCopyright ("Rob Gibbens")]
13 | [assembly: AssemblyTrademark ("")]
14 | [assembly: AssemblyCulture ("")]
15 |
16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
19 |
20 | [assembly: AssemblyVersion ("1.0.*")]
21 |
22 | // The following attributes are used to specify the signing key for the assembly,
23 | // if desired. See the Mono documentation for more information about signing.
24 |
25 | //[assembly: AssemblyDelaySign(false)]
26 | //[assembly: AssemblyKeyFile("")]
27 |
28 |
--------------------------------------------------------------------------------
/Core/TaskCounter.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 | using System.Threading.Tasks;
3 | using System.Threading;
4 | using FormsBackgrounding.Messages;
5 |
6 | namespace FormsBackgrounding
7 | {
8 | public class TaskCounter
9 | {
10 | public async Task RunCounter(CancellationToken token)
11 | {
12 | await Task.Run (async () => {
13 |
14 | for (long i = 0; i < long.MaxValue; i++) {
15 | token.ThrowIfCancellationRequested ();
16 |
17 | await Task.Delay(250);
18 | var message = new TickedMessage {
19 | Message = i.ToString()
20 | };
21 |
22 | Device.BeginInvokeOnMainThread(() => {
23 | MessagingCenter.Send(message, "TickedMessage");
24 | });
25 | }
26 | }, token);
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/Core/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Droid/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with your package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/Droid/FormsBackgrounding.Droid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
7 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}
8 | Library
9 | FormsBackgrounding.Droid
10 | Assets
11 | Resources
12 | Resource
13 | Resources\Resource.designer.cs
14 | True
15 | True
16 | FormsBackgrounding.Droid
17 | Properties\AndroidManifest.xml
18 | v5.1
19 |
20 |
21 |
22 |
23 | true
24 | full
25 | false
26 | bin\Debug
27 | DEBUG;
28 | prompt
29 | 4
30 | None
31 | false
32 |
33 |
34 | full
35 | true
36 | bin\Release
37 | prompt
38 | 4
39 | false
40 | false
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
51 |
52 |
53 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\MonoAndroid10\FormsViewGroup.dll
54 |
55 |
56 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\MonoAndroid10\Xamarin.Forms.Core.dll
57 |
58 |
59 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
60 |
61 |
62 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
63 |
64 |
65 | ..\packages\Xamarin.Android.Support.v4.22.2.1.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}
97 | FormsBackgrounding
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Droid/ImageHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Threading.Tasks;
4 | using Android.Graphics;
5 | using Android.Util;
6 |
7 | namespace FormsBackgrounding.Droid
8 | {
9 | public class ImageHelper
10 | {
11 | private string Path
12 | {
13 | get {
14 | string baseDir = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
15 | return System.IO.Path.Combine (baseDir, "monkey.png");
16 | }
17 | }
18 |
19 | private bool NeedsDownload ()
20 | {
21 | return !File.Exists (this.Path);
22 | }
23 |
24 | public Task DownloadImageAsync (string url)
25 | {
26 | if (NeedsDownload()) {
27 | return Task.Run (() => DownloadImage (url));
28 | } else {
29 | return Task.FromResult(this.Path);
30 | }
31 | }
32 |
33 | private string DownloadImage (string url)
34 | {
35 | try {
36 | using (var stream = new MemoryStream ()) {
37 | using (var imageUrl = new Java.Net.URL (url)) {
38 | var options = new BitmapFactory.Options {
39 | InSampleSize = 1,
40 | InPurgeable = true
41 | };
42 |
43 | var bit = BitmapFactory.DecodeStream (imageUrl.OpenStream (), null, options);
44 | bit.Compress (Bitmap.CompressFormat.Png, 70, stream);
45 | }
46 | var imageBytes = stream.ToArray ();
47 |
48 | File.WriteAllBytes (this.Path, imageBytes);
49 | }
50 | } catch (Exception ex) {
51 | Log.WriteLine (LogPriority.Error, "GetImageFromBitmap Error", ex.Message);
52 | }
53 |
54 | return this.Path;
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content;
3 | using Android.Content.PM;
4 | using Android.OS;
5 | using Xamarin.Forms;
6 | using FormsBackgrounding.Messages;
7 |
8 | namespace FormsBackgrounding.Droid
9 | {
10 | [Activity (Label = "FormsBackgrounding.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
11 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
12 | {
13 | protected override void OnCreate (Bundle bundle)
14 | {
15 | base.OnCreate (bundle);
16 |
17 | Forms.Init (this, bundle);
18 |
19 | LoadApplication(new App());
20 |
21 | WireUpLongRunningTask ();
22 | WireUpLongDownloadTask ();
23 | }
24 |
25 | void WireUpLongRunningTask()
26 | {
27 | MessagingCenter.Subscribe (this, "StartLongRunningTaskMessage", message => {
28 | var intent = new Intent(this, typeof(LongRunningTaskService));
29 | StartService(intent);
30 | });
31 |
32 | MessagingCenter.Subscribe (this, "StopLongRunningTaskMessage", message => {
33 | var intent = new Intent(this, typeof(LongRunningTaskService));
34 | StopService(intent);
35 | });
36 | }
37 |
38 | void WireUpLongDownloadTask ()
39 | {
40 | MessagingCenter.Subscribe (this, "Download", message => {
41 | var intent = new Intent (this, typeof(DownloaderService));
42 | intent.PutExtra ("url", message.Url);
43 | StartService (intent);
44 | });
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle ("FormsBackgrounding.Droid")]
9 | [assembly: AssemblyDescription ("")]
10 | [assembly: AssemblyConfiguration ("")]
11 | [assembly: AssemblyCompany ("Artek Software")]
12 | [assembly: AssemblyProduct ("")]
13 | [assembly: AssemblyCopyright ("Rob Gibbens")]
14 | [assembly: AssemblyTrademark ("")]
15 | [assembly: AssemblyCulture ("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion ("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
29 |
--------------------------------------------------------------------------------
/Droid/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/Droid/Resources/Resource.designer.cs:
--------------------------------------------------------------------------------
1 | #pragma warning disable 1591
2 | // ------------------------------------------------------------------------------
3 | //
4 | // This code was generated by a tool.
5 | // Mono Runtime Version: 4.0.30319.17020
6 | //
7 | // Changes to this file may cause incorrect behavior and will be lost if
8 | // the code is regenerated.
9 | //
10 | // ------------------------------------------------------------------------------
11 |
12 | [assembly: Android.Runtime.ResourceDesignerAttribute("FormsBackgrounding.Droid.Resource", IsApplication=true)]
13 |
14 | namespace FormsBackgrounding.Droid
15 | {
16 |
17 |
18 | [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
19 | public partial class Resource
20 | {
21 |
22 | static Resource()
23 | {
24 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
25 | }
26 |
27 | public static void UpdateIdValues()
28 | {
29 | global::Xamarin.Forms.Platform.Resource.String.ApplicationName = global::FormsBackgrounding.Droid.Resource.String.ApplicationName;
30 | global::Xamarin.Forms.Platform.Resource.String.Hello = global::FormsBackgrounding.Droid.Resource.String.Hello;
31 | }
32 |
33 | public partial class Attribute
34 | {
35 |
36 | static Attribute()
37 | {
38 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
39 | }
40 |
41 | private Attribute()
42 | {
43 | }
44 | }
45 |
46 | public partial class Drawable
47 | {
48 |
49 | // aapt resource value: 0x7f020000
50 | public const int icon = 2130837504;
51 |
52 | static Drawable()
53 | {
54 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
55 | }
56 |
57 | private Drawable()
58 | {
59 | }
60 | }
61 |
62 | public partial class String
63 | {
64 |
65 | // aapt resource value: 0x7f030001
66 | public const int ApplicationName = 2130903041;
67 |
68 | // aapt resource value: 0x7f030000
69 | public const int Hello = 2130903040;
70 |
71 | static String()
72 | {
73 | global::Android.Runtime.ResourceIdManager.UpdateIdValues();
74 | }
75 |
76 | private String()
77 | {
78 | }
79 | }
80 | }
81 | }
82 | #pragma warning restore 1591
83 |
--------------------------------------------------------------------------------
/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/Droid/Services/DownloaderService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Android.App;
3 | using Android.Content;
4 | using Android.OS;
5 | using System.Threading.Tasks;
6 | using Xamarin.Forms;
7 | using FormsBackgrounding.Messages;
8 |
9 | namespace FormsBackgrounding.Droid
10 | {
11 | [Service]
12 | public class DownloaderService : Service
13 | {
14 | public override IBinder OnBind (Intent intent)
15 | {
16 | return null;
17 | }
18 |
19 | public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
20 | {
21 | var url = intent.GetStringExtra ("url");
22 |
23 | Task.Run (() => {
24 | var imageHelper = new ImageHelper ();
25 | imageHelper.DownloadImageAsync (url)
26 | .ContinueWith (filePath => {
27 | var message = new DownloadFinishedMessage {
28 | FilePath = filePath.Result
29 | };
30 | MessagingCenter.Send (message, "DownloadFinishedMessage");
31 | });
32 | });
33 |
34 | return StartCommandResult.Sticky;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/Droid/Services/LongRunningTaskService.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content;
3 | using System.Threading.Tasks;
4 | using Android.OS;
5 | using System.Threading;
6 | using Xamarin.Forms;
7 | using FormsBackgrounding.Messages;
8 |
9 | namespace FormsBackgrounding.Droid
10 | {
11 | [Service]
12 | public class LongRunningTaskService : Service
13 | {
14 | CancellationTokenSource _cts;
15 |
16 | public override IBinder OnBind (Intent intent)
17 | {
18 | return null;
19 | }
20 |
21 | public override StartCommandResult OnStartCommand (Intent intent, StartCommandFlags flags, int startId)
22 | {
23 | _cts = new CancellationTokenSource ();
24 |
25 | Task.Run (() => {
26 | try {
27 | //INVOKE THE SHARED CODE
28 | var counter = new TaskCounter();
29 | counter.RunCounter(_cts.Token).Wait();
30 | }
31 | catch (OperationCanceledException) {
32 | }
33 | finally {
34 | if (_cts.IsCancellationRequested) {
35 | var message = new CancelledMessage();
36 | Device.BeginInvokeOnMainThread (
37 | () => MessagingCenter.Send(message, "CancelledMessage")
38 | );
39 | }
40 | }
41 |
42 | }, _cts.Token);
43 |
44 | return StartCommandResult.Sticky;
45 | }
46 |
47 | public override void OnDestroy ()
48 | {
49 | if (_cts != null) {
50 | _cts.Token.ThrowIfCancellationRequested ();
51 |
52 | _cts.Cancel ();
53 | }
54 | base.OnDestroy ();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Droid/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FormsBackgrounding.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | VisualStudioVersion = 14.0.22823.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsBackgrounding.iOS", "iOS\FormsBackgrounding.iOS.csproj", "{DC639DD0-57F2-4A1D-B37A-7546B296F008}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsBackgrounding.Droid", "Droid\FormsBackgrounding.Droid.csproj", "{2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsBackgrounding", "Core\FormsBackgrounding.csproj", "{3F591595-77FD-4AD5-A7DD-A6BDB88A4369}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|iPhone = Debug|iPhone
16 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
17 | Release|Any CPU = Release|Any CPU
18 | Release|iPhone = Release|iPhone
19 | Release|iPhoneSimulator = Release|iPhoneSimulator
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
25 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
26 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|iPhone.Build.0 = Debug|Any CPU
27 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
28 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
29 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|Any CPU.ActiveCfg = Release|Any CPU
30 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|Any CPU.Build.0 = Release|Any CPU
31 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|iPhone.ActiveCfg = Release|Any CPU
32 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|iPhone.Build.0 = Release|Any CPU
33 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
34 | {2CBA994D-4AB3-4C0C-B84B-6A1295F6305F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
35 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|Any CPU.Build.0 = Debug|Any CPU
37 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|iPhone.ActiveCfg = Debug|Any CPU
38 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|iPhone.Build.0 = Debug|Any CPU
39 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
40 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
41 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|iPhone.ActiveCfg = Release|Any CPU
44 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|iPhone.Build.0 = Release|Any CPU
45 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
46 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
47 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
48 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
49 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|iPhone.ActiveCfg = Debug|iPhone
50 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|iPhone.Build.0 = Debug|iPhone
51 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
52 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
53 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Debug|iPhoneSimulator.Deploy.0 = Debug|iPhoneSimulator
54 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|Any CPU.ActiveCfg = Release|iPhone
55 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|Any CPU.Build.0 = Release|iPhone
56 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|iPhone.ActiveCfg = Release|iPhone
57 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|iPhone.Build.0 = Release|iPhone
58 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
59 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
60 | EndGlobalSection
61 | GlobalSection(SolutionProperties) = preSolution
62 | HideSolutionNode = FALSE
63 | EndGlobalSection
64 | EndGlobal
65 |
--------------------------------------------------------------------------------
/XamarinFormsBackgrounding.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/XamarinFormsBackgrounding.zip
--------------------------------------------------------------------------------
/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 | using Xamarin.Forms;
4 | using System;
5 | using FormsBackgrounding.Messages;
6 |
7 | namespace FormsBackgrounding.iOS
8 | {
9 | [Register ("AppDelegate")]
10 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
11 | {
12 | void WireUpDownloadTask ()
13 | {
14 | MessagingCenter.Subscribe (this, "Download", async message => {
15 | var downloader = new Downloader (message.Url);
16 | await downloader.DownloadFile ();
17 | });
18 | }
19 |
20 | public static Action BackgroundSessionCompletionHandler;
21 |
22 | public override void HandleEventsForBackgroundUrl (UIApplication application, string sessionIdentifier, Action completionHandler)
23 | {
24 | Console.WriteLine ("HandleEventsForBackgroundUrl(): " + sessionIdentifier);
25 | // We get a completion handler which we are supposed to call if our transfer is done.
26 | BackgroundSessionCompletionHandler = completionHandler;
27 | }
28 |
29 | #region Methods
30 | iOSLongRunningTaskExample longRunningTaskExample;
31 |
32 | public override bool FinishedLaunching (UIApplication app, NSDictionary options)
33 | {
34 | Forms.Init ();
35 |
36 | LoadApplication (new App ());
37 |
38 | WireUpLongRunningTask ();
39 | WireUpDownloadTask ();
40 |
41 | return base.FinishedLaunching (app, options);
42 | }
43 |
44 | void WireUpLongRunningTask ()
45 | {
46 | MessagingCenter.Subscribe (this, "StartLongRunningTaskMessage", async message => {
47 | longRunningTaskExample = new iOSLongRunningTaskExample ();
48 | await longRunningTaskExample.Start ();
49 | });
50 |
51 | MessagingCenter.Subscribe (this, "StopLongRunningTaskMessage", message => {
52 | longRunningTaskExample.Stop ();
53 | });
54 | }
55 | #endregion
56 | }
57 | }
--------------------------------------------------------------------------------
/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/iOS/FormsBackgrounding.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | iPhoneSimulator
6 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
7 | {DC639DD0-57F2-4A1D-B37A-7546B296F008}
8 | Exe
9 | FormsBackgrounding.iOS
10 | Resources
11 | FormsBackgroundingiOS
12 |
13 |
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\iPhoneSimulator\Debug
20 | DEBUG;ENABLE_TEST_CLOUD;
21 | prompt
22 | 4
23 | false
24 | i386
25 | None
26 | true
27 | true
28 |
29 |
30 | full
31 | true
32 | bin\iPhone\Release
33 | prompt
34 | 4
35 | Entitlements.plist
36 | ARMv7, ARM64
37 | false
38 | iPhone Developer
39 |
40 |
41 | full
42 | true
43 | bin\iPhoneSimulator\Release
44 | prompt
45 | 4
46 | i386
47 | false
48 | None
49 |
50 |
51 | true
52 | full
53 | false
54 | bin\iPhone\Debug
55 | DEBUG;ENABLE_TEST_CLOUD;
56 | prompt
57 | 4
58 | false
59 | ARMv7, ARM64
60 | Entitlements.plist
61 | true
62 | iPhone Developer
63 | true
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
74 |
75 |
76 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
77 |
78 |
79 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
80 |
81 |
82 | ..\packages\Xamarin.Forms.1.4.4.6392\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | {3F591595-77FD-4AD5-A7DD-A6BDB88A4369}
129 | FormsBackgrounding
130 |
131 |
132 |
--------------------------------------------------------------------------------
/iOS/ITunesArtwork:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/ITunesArtwork
--------------------------------------------------------------------------------
/iOS/ITunesArtwork@2x:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/ITunesArtwork@2x
--------------------------------------------------------------------------------
/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | FormsBackgrounding
7 | CFBundleIdentifier
8 | com.arteksoftware.formsbackgrounding
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 | 7.0
17 | UIDeviceFamily
18 |
19 | 1
20 | 2
21 |
22 | UIRequiredDeviceCapabilities
23 |
24 | armv7
25 |
26 | UISupportedInterfaceOrientations
27 |
28 | UIInterfaceOrientationPortrait
29 | UIInterfaceOrientationLandscapeLeft
30 | UIInterfaceOrientationLandscapeRight
31 |
32 | UISupportedInterfaceOrientations~ipad
33 |
34 | UIInterfaceOrientationPortrait
35 | UIInterfaceOrientationPortraitUpsideDown
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | CFBundleIconFiles
40 |
41 | Icon-60@2x
42 | Icon-60@3x
43 | Icon-76
44 | Icon-76@2x
45 | Default
46 | Default@2x
47 | Default-568h
48 | Default-568h@2x
49 | Default-Landscape
50 | Default-Landscape@2x
51 | Default-Portrait
52 | Default-Portrait@2x
53 | Icon-Small-40
54 | Icon-Small-40@2x
55 | Icon-Small-40@3x
56 | Icon-Small
57 | Icon-Small@2x
58 | Icon-Small@3x
59 |
60 | UILaunchStoryboardName
61 | LaunchScreen
62 |
63 |
64 |
--------------------------------------------------------------------------------
/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace FormsBackgrounding.iOS
4 | {
5 | public class Application
6 | {
7 | static void Main (string[] args)
8 | {
9 | UIApplication.Main (args, null, "AppDelegate");
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/iOS/Resources/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Default-568h@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Default-Portrait.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Default-Portrait.png
--------------------------------------------------------------------------------
/iOS/Resources/Default-Portrait@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Default-Portrait@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Default.png
--------------------------------------------------------------------------------
/iOS/Resources/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Default@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-60@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-60@3x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-76.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-76@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small-40.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small@2x.png
--------------------------------------------------------------------------------
/iOS/Resources/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RobGibbens/XamarinFormsBackgrounding/31fe518f87376a75b31a06a1c62dc8d8563cf63d/iOS/Resources/Icon-Small@3x.png
--------------------------------------------------------------------------------
/iOS/Resources/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/iOS/Services/CustomSessionDownloadDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using Xamarin.Forms;
3 | using System;
4 | using FormsBackgrounding.Messages;
5 |
6 | namespace FormsBackgrounding.iOS
7 | {
8 | public class CustomSessionDownloadDelegate : NSUrlSessionDownloadDelegate
9 | {
10 | public override void DidWriteData (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite)
11 | {
12 | float percentage = (float)totalBytesWritten / (float)totalBytesExpectedToWrite;
13 |
14 | var message = new DownloadProgressMessage () {
15 | BytesWritten = bytesWritten,
16 | TotalBytesExpectedToWrite = totalBytesExpectedToWrite,
17 | TotalBytesWritten = totalBytesWritten,
18 | Percentage = percentage
19 | };
20 |
21 | MessagingCenter.Send (message, "DownloadProgressMessage");
22 | }
23 |
24 | public override void DidFinishDownloading (NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location)
25 | {
26 | CopyDownloadedImage (location);
27 |
28 | var message = new DownloadFinishedMessage () {
29 | FilePath = targetFileName,
30 | Url = downloadTask.OriginalRequest.Url.AbsoluteString
31 | };
32 |
33 | MessagingCenter.Send (message, "DownloadFinishedMessage");
34 |
35 | }
36 |
37 | #region Methods
38 | readonly string targetFileName;
39 |
40 | public CustomSessionDownloadDelegate (string targetFileName) : base ()
41 | {
42 | this.targetFileName = targetFileName;
43 | }
44 |
45 |
46 | public override void DidCompleteWithError (NSUrlSession session, NSUrlSessionTask task, NSError error)
47 | {
48 | if (error == null) {
49 | return;
50 | }
51 |
52 | Console.WriteLine ("DidCompleteWithError - Task: {0}, Error: {1}", task.TaskIdentifier, error);
53 |
54 | task.Cancel ();
55 | }
56 |
57 | public override void DidFinishEventsForBackgroundSession (NSUrlSession session)
58 | {
59 | var handler = AppDelegate.BackgroundSessionCompletionHandler;
60 | AppDelegate.BackgroundSessionCompletionHandler = null;
61 | if (handler != null) {
62 | handler.Invoke ();
63 | }
64 | }
65 |
66 | private void CopyDownloadedImage (NSUrl location)
67 | {
68 | NSFileManager fileManager = NSFileManager.DefaultManager;
69 | NSError error;
70 | if (fileManager.FileExists (targetFileName)) {
71 | fileManager.Remove (targetFileName, out error);
72 | }
73 | bool success = fileManager.Copy (location.Path, targetFileName, out error);
74 | if (!success) {
75 | Console.WriteLine ("Error during the copy: {0}", error.LocalizedDescription);
76 | }
77 | }
78 |
79 | #endregion
80 | }
81 | }
--------------------------------------------------------------------------------
/iOS/Services/Downloader.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 | using System;
4 | using System.IO;
5 | using System.Threading.Tasks;
6 |
7 | namespace FormsBackgrounding.iOS
8 | {
9 | public class Downloader
10 | {
11 | private string targetFilename = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "huge_monkey.png");
12 |
13 | private const string sessionId = "com.xamarin.transfersession";
14 |
15 | private NSUrlSession session;
16 |
17 | readonly string _downloadFileUrl;
18 |
19 | public Downloader (string downloadFileUrl)
20 | {
21 | this._downloadFileUrl = downloadFileUrl;
22 | }
23 |
24 | public async Task DownloadFile ()
25 | {
26 | this.InitializeSession ();
27 |
28 | var pendingTasks = await this.session.GetTasksAsync ();
29 | if (pendingTasks != null && pendingTasks.DownloadTasks != null) {
30 | foreach (var task in pendingTasks.DownloadTasks) {
31 | task.Cancel ();
32 | }
33 | }
34 |
35 | if (File.Exists (targetFilename)) {
36 | File.Delete (targetFilename);
37 | }
38 |
39 | this.EnqueueDownload ();
40 | }
41 |
42 | void InitializeSession ()
43 | {
44 | using (var sessionConfig = UIDevice.CurrentDevice.CheckSystemVersion (8, 0)
45 | ? NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration (sessionId)
46 | : NSUrlSessionConfiguration.BackgroundSessionConfiguration (sessionId)) {
47 | sessionConfig.AllowsCellularAccess = true;
48 |
49 | sessionConfig.NetworkServiceType = NSUrlRequestNetworkServiceType.Default;
50 |
51 | sessionConfig.HttpMaximumConnectionsPerHost = 2;
52 |
53 | var sessionDelegate = new CustomSessionDownloadDelegate (targetFilename);
54 | this.session = NSUrlSession.FromConfiguration (sessionConfig, sessionDelegate, null);
55 | }
56 | }
57 |
58 | void EnqueueDownload ()
59 | {
60 | var downloadTask = this.session.CreateDownloadTask (NSUrl.FromString (_downloadFileUrl));
61 |
62 | if (downloadTask == null) {
63 | new UIAlertView (string.Empty, "Failed to create download task! Please retry.", null, "OK").Show ();
64 | return;
65 | }
66 |
67 | downloadTask.Resume ();
68 | Console.WriteLine ("Starting download. State of task: '{0}'. ID: '{1}'", downloadTask.State, downloadTask.TaskIdentifier);
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/iOS/Services/iOSLongRunningTaskExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using FormsBackgrounding.Messages;
5 | using UIKit;
6 | using Xamarin.Forms;
7 |
8 | namespace FormsBackgrounding.iOS
9 | {
10 | public class iOSLongRunningTaskExample
11 | {
12 | nint _taskId;
13 | CancellationTokenSource _cts;
14 |
15 | public async Task Start ()
16 | {
17 | _cts = new CancellationTokenSource ();
18 |
19 | _taskId = UIApplication.SharedApplication.BeginBackgroundTask ("LongRunningTask", OnExpiration);
20 |
21 | try {
22 | //INVOKE THE SHARED CODE
23 | var counter = new TaskCounter();
24 | await counter.RunCounter(_cts.Token);
25 |
26 | } catch (OperationCanceledException) {
27 | } finally {
28 | if (_cts.IsCancellationRequested) {
29 | var message = new CancelledMessage();
30 | Device.BeginInvokeOnMainThread (
31 | () => MessagingCenter.Send(message, "CancelledMessage")
32 | );
33 | }
34 | }
35 |
36 | UIApplication.SharedApplication.EndBackgroundTask (_taskId);
37 | }
38 |
39 | public void Stop ()
40 | {
41 | _cts.Cancel ();
42 | }
43 |
44 | void OnExpiration ()
45 | {
46 | _cts.Cancel ();
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/iOS/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------