Skip to content
This repository was archived by the owner on May 15, 2024. It is now read-only.

Commit 480cac0

Browse files
mattleibowRedth
authored andcommitted
A few fixes for the release. (#228)
* Setting the correct flags for Chrome Tabs. Fixes #225 * Make sure that there is data to decrypt before starting. Fixes #226 * Fixes for TTS. Fixes #227 * A bit of the fixes for emails on iOS. Relates to #224 * Update the email bit for iOS #224 * Cleaning up the code #224
1 parent 9295ce3 commit 480cac0

File tree

5 files changed

+104
-46
lines changed

5 files changed

+104
-46
lines changed

Xamarin.Essentials/Browser/Browser.android.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ static Task PlatformOpenAsync(Uri uri, BrowserLaunchType launchType)
2121
{
2222
case BrowserLaunchType.SystemPreferred:
2323
var tabsBuilder = new CustomTabsIntent.Builder();
24-
var tabsIntent = tabsBuilder.Build();
2524
tabsBuilder.SetShowTitle(true);
25+
var tabsIntent = tabsBuilder.Build();
26+
tabsIntent.Intent.SetFlags(ActivityFlags.ClearTop);
27+
tabsIntent.Intent.SetFlags(ActivityFlags.NewTask);
2628
tabsIntent.LaunchUrl(Platform.AppContext, nativeUri);
2729
break;
2830
case BrowserLaunchType.External:

Xamarin.Essentials/Email/Email.ios.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,35 @@
11
using System.Threading.Tasks;
2+
using Foundation;
23
using MessageUI;
4+
using UIKit;
35

46
namespace Xamarin.Essentials
57
{
68
public static partial class Email
79
{
810
internal static bool IsComposeSupported
9-
=> MFMailComposeViewController.CanSendMail;
11+
{
12+
get
13+
{
14+
var can = MFMailComposeViewController.CanSendMail;
15+
if (!can)
16+
{
17+
var url = NSUrl.FromString("mailto:");
18+
NSRunLoop.Main.InvokeOnMainThread(() => can = UIApplication.SharedApplication.CanOpenUrl(url));
19+
}
20+
return can;
21+
}
22+
}
1023

1124
static Task PlatformComposeAsync(EmailMessage message)
25+
{
26+
if (MFMailComposeViewController.CanSendMail)
27+
return ComposeWithMailCompose(message);
28+
else
29+
return ComposeWithUrl(message);
30+
}
31+
32+
static Task ComposeWithMailCompose(EmailMessage message)
1233
{
1334
// do this first so we can throw as early as possible
1435
var parentController = Platform.GetCurrentViewController();
@@ -37,5 +58,18 @@ static Task PlatformComposeAsync(EmailMessage message)
3758

3859
return tcs.Task;
3960
}
61+
62+
static Task ComposeWithUrl(EmailMessage message)
63+
{
64+
var url = GetMailToUri(message);
65+
66+
var tcs = new TaskCompletionSource<bool>();
67+
NSRunLoop.Main.InvokeOnMainThread(() =>
68+
{
69+
var nsurl = NSUrl.FromString(url);
70+
UIApplication.SharedApplication.OpenUrl(nsurl, new UIApplicationOpenUrlOptions(), r => tcs.TrySetResult(r));
71+
});
72+
return tcs.Task;
73+
}
4074
}
4175
}

Xamarin.Essentials/Email/Email.shared.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Threading.Tasks;
45

@@ -19,6 +20,29 @@ public static Task ComposeAsync(EmailMessage message)
1920

2021
return PlatformComposeAsync(message);
2122
}
23+
24+
static string GetMailToUri(EmailMessage message)
25+
{
26+
if (message != null && message.BodyFormat != EmailBodyFormat.PlainText)
27+
throw new FeatureNotSupportedException("Only EmailBodyFormat.PlainText is supported if no email account is set up.");
28+
29+
var parts = new List<string>();
30+
if (!string.IsNullOrEmpty(message?.Body))
31+
parts.Add("body=" + Uri.EscapeUriString(message.Body));
32+
if (!string.IsNullOrEmpty(message?.Subject))
33+
parts.Add("subject=" + Uri.EscapeUriString(message.Subject));
34+
if (message?.To.Count > 0)
35+
parts.Add("to=" + string.Join(",", message.To));
36+
if (message?.Cc.Count > 0)
37+
parts.Add("cc=" + string.Join(",", message.Cc));
38+
if (message?.Bcc.Count > 0)
39+
parts.Add("bcc=" + string.Join(",", message.Bcc));
40+
41+
var uri = "mailto:";
42+
if (parts.Count > 0)
43+
uri += "?" + string.Join("&", parts);
44+
return uri;
45+
}
2246
}
2347

2448
public class EmailMessage

Xamarin.Essentials/SecureStorage/SecureStorage.android.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ static Task<string> PlatformGetAsync(string key)
2222
using (var prefs = context.GetSharedPreferences(Alias, FileCreationMode.Private))
2323
encStr = prefs.GetString(Utils.Md5Hash(key), null);
2424

25-
var encData = Convert.FromBase64String(encStr);
26-
27-
var ks = new AndroidKeyStore(context, Alias, AlwaysUseAsymmetricKeyStorage);
28-
var decryptedData = ks.Decrypt(encData);
25+
string decryptedData = null;
26+
if (!string.IsNullOrEmpty(encStr))
27+
{
28+
var encData = Convert.FromBase64String(encStr);
29+
var ks = new AndroidKeyStore(context, Alias, AlwaysUseAsymmetricKeyStorage);
30+
decryptedData = ks.Decrypt(encData);
31+
}
2932

3033
return Task.FromResult(decryptedData);
3134
}

Xamarin.Essentials/TextToSpeech/TextToSpeech.android.cs

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ internal class TextToSpeechImplementation : Java.Lang.Object, AndroidTextToSpeec
6161
TaskCompletionSource<bool> tcsInitialize;
6262
TaskCompletionSource<bool> tcsUtterances;
6363

64-
public TextToSpeechImplementation()
65-
{
66-
}
67-
6864
Task<bool> Initialize()
6965
{
7066
if (tcsInitialize != null && tts != null)
@@ -88,11 +84,16 @@ Task<bool> Initialize()
8884
return tcsInitialize.Task;
8985
}
9086

91-
public new void Dispose()
87+
protected override void Dispose(bool disposing)
9288
{
93-
tts?.Stop();
94-
tts?.Shutdown();
95-
tts = null;
89+
if (disposing)
90+
{
91+
tts?.Stop();
92+
tts?.Shutdown();
93+
tts = null;
94+
}
95+
96+
base.Dispose(disposing);
9697
}
9798

9899
int numExpectedUtterances = 0;
@@ -138,10 +139,9 @@ public async Task SpeakAsync(string text, int max, SpeakSettings settings, Cance
138139
}
139140

140141
if (settings?.Pitch.HasValue ?? false)
141-
{
142-
var pitch = settings.Pitch.Value;
143-
tts.SetPitch(pitch);
144-
}
142+
tts.SetPitch(settings.Pitch.Value);
143+
else
144+
tts.SetPitch(TextToSpeech.PitchDefault);
145145

146146
var parts = text.SplitSpeak(max);
147147

@@ -150,11 +150,8 @@ public async Task SpeakAsync(string text, int max, SpeakSettings settings, Cance
150150

151151
var guid = Guid.NewGuid().ToString();
152152

153-
for (var i = 0; i < parts.Count; i++)
153+
for (var i = 0; i < parts.Count && !cancelToken.IsCancellationRequested; i++)
154154
{
155-
if (cancelToken.IsCancellationRequested)
156-
break;
157-
158155
// We require the utterance id to be set if we want the completed listener to fire
159156
var map = new Dictionary<string, string>
160157
{
@@ -164,10 +161,9 @@ public async Task SpeakAsync(string text, int max, SpeakSettings settings, Cance
164161
if (settings != null && settings.Volume.HasValue)
165162
map.Add(AndroidTextToSpeech.Engine.KeyParamVolume, settings.Volume.Value.ToString());
166163

167-
#pragma warning disable CS0618
168-
169164
// We use an obsolete overload here so it works on older API levels at runtime
170165
// Flush on first entry and add (to not flush our own previous) subsequent entries
166+
#pragma warning disable CS0618
171167
tts.Speak(parts[i], i == 0 ? QueueMode.Flush : QueueMode.Add, map);
172168
#pragma warning restore CS0618
173169
}
@@ -178,13 +174,9 @@ public async Task SpeakAsync(string text, int max, SpeakSettings settings, Cance
178174
public void OnInit(OperationResult status)
179175
{
180176
if (status.Equals(OperationResult.Success))
181-
{
182177
tcsInitialize.TrySetResult(true);
183-
}
184178
else
185-
{
186179
tcsInitialize.TrySetException(new ArgumentException("Failed to initialize Text to Speech engine."));
187-
}
188180
}
189181

190182
public async Task<IEnumerable<Locale>> GetLocalesAsync()
@@ -203,27 +195,30 @@ public async Task<IEnumerable<Locale>> GetLocalesAsync()
203195
}
204196
}
205197

206-
return JavaLocale.GetAvailableLocales().
207-
Where(l =>
208-
{
209-
try
210-
{
211-
var r = tts.IsLanguageAvailable(l);
212-
return r == LanguageAvailableResult.Available
213-
|| r == LanguageAvailableResult.CountryAvailable
214-
|| r == LanguageAvailableResult.CountryVarAvailable;
215-
}
216-
catch (Exception ex)
217-
{
218-
Console.WriteLine("Error checking language; " + l + " " + ex);
219-
}
220-
return false;
221-
}).
222-
Select(l => new Locale(l.Language, l.Country, l.DisplayName, string.Empty))
198+
return JavaLocale.GetAvailableLocales()
199+
.Where(IsLocaleAvailable)
200+
.Select(l => new Locale(l.Language, l.Country, l.DisplayName, string.Empty))
223201
.GroupBy(c => c.ToString())
224202
.Select(g => g.First());
225203
}
226204

205+
private bool IsLocaleAvailable(JavaLocale l)
206+
{
207+
try
208+
{
209+
var r = tts.IsLanguageAvailable(l);
210+
return
211+
r == LanguageAvailableResult.Available ||
212+
r == LanguageAvailableResult.CountryAvailable ||
213+
r == LanguageAvailableResult.CountryVarAvailable;
214+
}
215+
catch (Exception ex)
216+
{
217+
Console.WriteLine("Error checking language; " + l + " " + ex);
218+
}
219+
return false;
220+
}
221+
227222
public void OnUtteranceCompleted(string utteranceId)
228223
{
229224
numCompletedUtterances++;

0 commit comments

Comments
 (0)