Monotouch Sending SMS using MFMessageComposeViewController - iphone

need ur help. Im writing iphone app, which must often send sms with different content
Im using static class and procedure sendSms(string body) looks like
if (MFMessageComposeViewController.CanSendText) {
MFMessageComposeViewController message =
new MFMessageComposeViewController ();
message.MessageComposeDelegate = new CustomMessageComposeDelegate ();
message.Recipients = new string[] { receiver };
message.Body = body;
this.NavigationController.PresentModalViewController (message, true);
}
public class CustomMessageComposeDelegate : MFMessageComposeViewControllerDelegate
{
public override void Finished (MFMessageComposeViewController controller,
MessageComposeResult result)
{
"Code for dismissing"
}
}
it works, but only for one SMS, ok it sended.
But if ill try to write another sms,
it will display SMS with old body and old recipients.
I know - "The message composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is unable to make further changes to the SMS content. The user can edit the content using the interface, but programmatic changes are ignored. Thus, you must set the values of content fields, if desired, before presenting the interface"
But how to create always new MFMessageComposeViewController and fill always new body and recipients?

Related

xamarin forms: Calling phone and sending email (IOS, Android and UWP)

Currently using following code for calling and email features, but it is only working in Android and not working in IOS. Also, I need these features in UWP.
For call:
string phoneno = "1234567890";
Device.OpenUri(new Uri("tel:" + phoneno));
For mail:
string email = "sreejithsree139#gmail.com";
Device.OpenUri(new Uri("mailto:" + email ));
Any package available for this?
Xamarin.Essentials (Nuget) is available as a preview package and contains functionality to both open the default mail app and attach information such as the recipients, subject and the body as well as open the phone dialer with a certain number.
There is also a blog post about Xamarin.Essentials available on blog.xamarin.com.
Edit:
As for your mail issue, Xamarin.Essentials expects an array of strings as recipients so you are able to send mail to multiple people at once. Just pass a string array with one single value.
var recipients = new string[1] {"me#watercod.es"};
If you're using the overload that expects an EmailMessage instance, you are supposed to pass a List of string objects.
In that case, the following should work:
var recipients = new List<string> {"me#watercod.es"};
Updating the complete code for calling and mailing features using Xamarin.Essentials, this might help others.
For call:
try
{
PhoneDialer.Open(number);
}
catch (ArgumentNullException anEx)
{
// Number was null or white space
}
catch (FeatureNotSupportedException ex)
{
// Phone Dialer is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
For Mail:
List<string> recipients = new List<string>();
string useremail = email.Text;
recipients.Add(useremail);
try
{
var message = new EmailMessage
{
//Subject = subject,
//Body = body,
To = recipients
//Cc = ccRecipients,
//Bcc = bccRecipients
};
await Email.ComposeAsync(message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception:>>"+ex);
}
Hello to make a call in UWP:
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.ApplicationModel.Calls.PhoneCallManager"))
{
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI("123", "name to call");
}
To send a Text:
private async void ComposeSms(Windows.ApplicationModel.Contacts.Contact recipient,
string messageBody,
StorageFile attachmentFile,
string mimeType)
{
var chatMessage = new Windows.ApplicationModel.Chat.ChatMessage();
chatMessage.Body = messageBody;
if (attachmentFile != null)
{
var stream = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(attachmentFile);
var attachment = new Windows.ApplicationModel.Chat.ChatMessageAttachment(
mimeType,
stream);
chatMessage.Attachments.Add(attachment);
}
var phone = recipient.Phones.FirstOrDefault<Windows.ApplicationModel.Contacts.ContactPhone>();
if (phone != null)
{
chatMessage.Recipients.Add(phone.Number);
}
await Windows.ApplicationModel.Chat.ChatMessageManager.ShowComposeSmsMessageAsync(chatMessage);
}
as found in Microsoft documentation here: Compose SMS documentation
==> So you can make (If not already done) a shared service interface in your Xamarin app, then the implementation with these codes in your UWP app...
To send an email:
To send an email in UWP, you can refer to the Microsoft documentation too:
Send Email documentation (UWP)
Using a plugin
Else you can use a Xamarin plugin:
documentation: Xamarin cross messaging plugin
Nuget: Nuget plugin package
In our app, we are doing the phone calling with a DependencyService.
Therefore in our PCL, we have
public interface IPhoneCall
{
void Call(string number);
}
On the iOS side, the following method does the calling:
public void Call(string number)
{
if (string.IsNullOrEmpty(number))
return;
var url = new NSUrl("tel:" + number);
if (!UIApplication.SharedApplication.OpenUrl(url))
{
var av = new UIAlertView("Error",
"Your device does not support calls",
null,
Keys.Messages.BUTTON_OK,
null);
av.Show();
}
}
If don't want to wait for the Xamarin essentials that is still in pre-release as of today, you can use this open source plugin. It works on iOS, Android and UWP. There is a sample from the github documentation :
// Make Phone Call
var phoneDialer = CrossMessaging.Current.PhoneDialer;
if (phoneDialer.CanMakePhoneCall)
phoneDialer.MakePhoneCall("+27219333000");
// Send Sms
var smsMessenger = CrossMessaging.Current.SmsMessenger;
if (smsMessenger.CanSendSms)
smsMessenger.SendSms("+27213894839493", "Well hello there from Xam.Messaging.Plugin");
var emailMessenger = CrossMessaging.Current.EmailMessenger;
if (emailMessenger.CanSendEmail)
{
// Send simple e-mail to single receiver without attachments, bcc, cc etc.
emailMessenger.SendEmail("to.plugins#xamarin.com", "Xamarin Messaging Plugin", "Well hello there from Xam.Messaging.Plugin");
// Alternatively use EmailBuilder fluent interface to construct more complex e-mail with multiple recipients, bcc, attachments etc.
var email = new EmailMessageBuilder()
.To("to.plugins#xamarin.com")
.Cc("cc.plugins#xamarin.com")
.Bcc(new[] { "bcc1.plugins#xamarin.com", "bcc2.plugins#xamarin.com" })
.Subject("Xamarin Messaging Plugin")
.Body("Well hello there from Xam.Messaging.Plugin")
.Build();
emailMessenger.SendEmail(email);
}

Email Sending .NET Core

I just want to have a function, which will be sending mail to different people.
I have written a Email Service, just like this:
public void SendEMail(EMail mail)
{
var body = JObject.FromObject(settings);
body.Merge(JObject.FromObject(mail));
GlobalTelemetry.TrackDependency("E-Mail Service", "Send", () =>
{
var result = AsyncHelper.RunSync(() => httpClient.PostAsync(azureFunctionUrl,
new StringContent(body.ToString(), Encoding.UTF8, "application/json")));
if (!result.IsSuccessStatusCode)
{
throw new InvalidOperationException(
$"E-Mail Service failed to send mails. Http Status {result.StatusCode}. Please check if the Url '{azureFunctionUrl}' is correct. Env: {Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}");
}
});
}
and by every other functions, which want to use this mail service, do just like this:
SendMail = mail =>
{
var fireAndForgetTask = Task.Run(() =>
{
try
{
eMailService.SendEMail(mail);
}
catch (Exception e)
{
Log.Fatal(e, $"Fail to send E-Mail to: '{mail.To}'");
}
});
};
it does work, but fireAndForgetTask is not used, I have no idea how to do it better.
Is it necessary to write a Email Job???
Some better suggestion is welcome :-)
I had a similar issue in my app for sending a password reset email, I did not want the delay of waiting for the email to send because if a hacker is trying to find out if an account exists for an email address the delay could indicate that the account does exist. So I wanted to fire and forget the email with no delay.
So I implemented a simple extension method named forget like this in a separate static class based on this so question:
public static void Forget(this Task task)
{
}
and then I send my email async and use that .Forget extension to not wait for it like this:
emailSender.SendPasswordResetEmailAsync(
Site,
model.Email,
sr["Reset Password"],
resetUrl).Forget();
note that I am not using "await" when I call this async method and the .Forget gets rid of the warning that would otherwise appear in Visual Studio when calling an async method without the await keyword

Add Email Signature to Email Notification Script

I am writing a code on Google Apps Script to send an email every time there is a new announcement made in my site. Here is the code for reference:
var url_of_announcements_page = "https://sites.google.com/announcements";
var who_to_email = "emailaccount";
function emailAnnouncements(){
var page = SitesApp.getPageByUrl(url_of_announcements_page);
if(page.getPageType() == SitesApp.PageType.ANNOUNCEMENTS_PAGE){
var announcements = page.getAnnouncements({ start: 0,
max: 10,
includeDrafts: false,
includeDeleted: false});
announcements.reverse();
for(var i in announcements) {
var ann = announcements[i];
var updated = ann.getLastUpdated().getTime();
if (updated > PropertiesService.getScriptProperties().getProperty("last-update")){
var options = {};
options.htmlBody = Utilities.formatString("<h1><a href='%s'>%s</a></h1>%s", ann.getUrl(), ann.getTitle(), ann.getHtmlContent());
MailApp.sendEmail(who_to_email, "Announcement - '"+ann.getTitle()+"'", ann.getTextContent()+"\n\n"+ann.getUrl(), options);
PropertiesService.getScriptProperties().setProperty('last-update',updated);
}
}
}
}
function setup(){
PropertiesService.getScriptProperties().setProperty('last-update',new Date().getTime());
}
I would like to know if it is possible to add my gmail signature to the code. As when I send it with the script my signature is removed. Do I have to make my signature in the code or am i able to get my signature from gmail and automatically insert it at the end? Here is the line for the formatting of the email:
MailApp.sendEmail(who_to_email, "Announcement - '"+ann.getTitle()+"'", ann.getTextContent()+"\n\n"+ann.getUrl(), options);
Apps Script cannot access user's signature: there is no method for that in MailApp, or GmailApp, or even in Gmail API accessible via Advanced Google Services.
In principle, you could use GmailApp to get a recent outgoing message and search its text for the signature contained after the last -- found in message body. But this requires giving the script a lot more access (GmailApp can access, forward and delete existing email, unlike MailApp) and is error-prone (when text parsing fails, you might end up with an embarrassing fragment of text in your message).
Just append it directly:
var signature = "\n\n--\nFirstName LastName";
// ...
MailApp.sendEmail(... +signature, options);
(By the way, Gmail web interface and Gmail mobile app have different user signatures in general, so having another one for script-generated messages doesn't seem unusual.)

Callback function issues in FB.API for Unity

I am using Unity 5.5.2f1 pro and facebook's SDK v 7.9.4
I have a script which after login (managed in a previous scene) sends an API request to FB asking for friends, name and email and sends that info as a POST to a php website.
code:
[Serializable]
public struct FBData {
public string first_name;
public string email;
public string friends;
public string id;}
public class UserManagement : MonoBehaviour {
string urlSaveUserData="some php website";
public Text testTxt;
FBData parsedData;
// Use this for initialization
void Start () {
//Check if it's the first time the user is opening the app.
if (UserInfo.FIRST_TIME) {
//update text (only used for testing, should be removed in production.)
testTxt.text = "Your user id is: " + UserInfo.ID;
//Perform FB.API call to get User Data.
getUserData ();
//Save in SQL table. (won't get here if line in getUserData() is active)
StartCoroutine ("saveUserData");
} else {
//do something else.
}
note: Since this is meant for iOS I have to test it on a device so I'm using text in the screen to display info (think of it as a badly implemented print statement).
The problem: In my callback function for FB.API I write in the text Gameobject (aka testTxt) the parsed information from the response which is saved in the Custom UserInfo clss. It display's correctly but the code gets stuck there. It doesn't continue to the next function. HOWEVER, if I delete/comment that line and don't display anything in the text field. The codes does continue to the POST function BUT the information from the API call is not passed, i.e my custom class is empty (leading me to believe the callback function is not called at all).
public void getUserData(){
string query = "me?fields=first_name,email,friends";
FB.API (query, HttpMethod.GET, Apicallback, new Dictionary<string, string> ());
}
private void Apicallback(IGraphResult result){
//Parse Graph response into a specific class created for this result.
parsedData = JsonUtility.FromJson<FBData>(result.RawResult);
//Pass each field into UserInfo class.
UserInfo.EMAIL = parsedData.email;
UserInfo.FRIENDS = parsedData.friends;
UserInfo.NAME = parsedData.first_name;
UserInfo.FACEBOOKID = parsedData.id;
/*problem area, if I comment line below, then previous information is apparently not stored. If left as is then testTxt displays correct information but code gets stuck there. */
testTxt.text = "This is the info from USerInfoInside the APICallback: " + UserInfo.EMAIL + UserInfo.FRIENDS + UserInfo.FACEBOOKID;
}
The function below is to send info to php website, is there for illustrative purposes:
code:
public IEnumerator saveUserData() {
//get user info (this information is EMPTY if line in getUserData() is commented.
parsedData.id = UserInfo.FACEBOOKID;
parsedData.friends = UserInfo.FRIENDS;
parsedData.first_name = UserInfo.NAME;
parsedData.email = UserInfo.EMAIL;
//translate data into json
string JsonBodyData = JsonUtility.ToJson (parsedData);
//Custom web request (POST method doesnt seem to work very well, documentation example sends empty form)
var w = new UnityWebRequest(urlSaveUserData, "POST");
byte[] bodyRaw = new System.Text.UTF8Encoding().GetBytes(JsonBodyData);
w.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
w.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
w.SetRequestHeader("Content-Type", "application/json");
yield return w.Send();
//work with received data...}
Im stuck here any help is appreciated. Thanks!
Be sure to use EscapeURL when using strings directly for JSON or HTTP POST and GET methods. The lack of this treatment tends to screw things over, particulary in iOS platforms.
From what I can see, this code
string query = "me?fields=first_name,email,friends";
should instead be escaped as
string query = WWW.EscapeURL("me?fields=first_name,email,friends");
so characters like "?" won't get encoded as an URL symbol.
I'm assuming you don't need to do that for your illustrative example, because UnityWebRequest already escapes your POST request strings internally, but I can't fully confirm that.

How to retrieve Someone's Avatar/Photo with agsXmpp

this is what I have so far:
void xmppConnection_OnReadXml(object sender, string xml)
{
if (xml.Contains(XmlTags.PhotoOpen))
{
int startIndex = xml.IndexOf(XmlTags.PhotoOpen) + XmlTags.PhotoOpen.Length;
int length = xml.IndexOf(XmlTags.PhotoClose) - startIndex;
string photoHash = xml.Substring(startIndex, length);
}
}
I guess I can't undo the hash, but I want to the get a person's avatar/photo. How do I achieve this?
You need to handle the VCard events and responses from XMPP connection:
private void vcardToolStripMenuItem_Click(object sender, EventArgs e)
{
RosterNode node = rosterControl.SelectedItem();
if (node != null)
{
frmVcard f = new frmVcard(node.RosterItem.Jid, XmppCon);
f.Show();
}
}
The above is from the miniclient solution example from the AGSXMPP download. Note, it happens when a user request a VCARD for a user. You can initiate that request whenever you want, however.
private void VcardResult(object sender, IQ iq, object data)
{
if (InvokeRequired)
{
// Windows Forms are not Thread Safe, we need to invoke this :(
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(new IqCB(VcardResult), new object[] { sender, iq, data });
return;
}
if (iq.Type == IqType.result)
{
Vcard vcard = iq.Vcard;
if (vcard!=null)
{
txtFullname.Text = vcard.Fullname;
txtNickname.Text = vcard.Nickname;
txtBirthday.Text = vcard.Birthday.ToString();
txtDescription.Text = vcard.Description;
Photo photo = vcard.Photo;
if (photo != null)
picPhoto.Image = vcard.Photo.Image;
}
}
}
That is what happens when someone requests the VCARD information from XMPP and the IQ type matches the proper data. You can thenpull the photo from vcard.Photo.
You trigger the pull with:
VcardIq viq = new VcardIq(IqType.get, new Jid(jid.Bare));
con.IqGrabber.SendIq(viq, new IqCB(VcardResult), null);
The first line there is the request to the XMPP server, that the VCARD form uses to request user information.
The second line there, sets up another grabber (callback of sorts), that the form uses to wait for the information to arrive, and then parse out the necessary information. IN this case, the grabber is in a new form, so that the main application doesn't have to worry about parsing that information.
You can look at the entire source by extracting the AGSXMPP zip file to your local drive, and looking in the Samples\VS2008\miniclient folder.
You can click link:http://forum.ag-software.de/thread/192-How-to-save-vcard-data