Applewatch Messages Url Works Hard Coded But Not with Variables

AppleWatch Messages URL works hard coded but not with variables

My guess is that it is not the acctual openSystemUrl call that is the problem. I believe there must be something with the code that is building the number string programmatically.

The code bellow is a simplified version of all the code you have posted. I have confirmed that it is working on my Apple Watch. It opens the Messages app with pre-populated numbers & body text.

Take one more look at your code and see if there is something your missing. If you can't find anything, just delete the code and re-write it, probably will be faster then spotting the weird issue.

Once again the code bellow is confirmed working as expected, so you should be able to get it to work. (or just copy & paste my code) :)

class InterfaceController: WKInterfaceController {

@IBAction func doItButton() {
if let urlSafeBody = createBody() {
if let url = NSURL(string: "sms:/open?addresses=\(createNumbers())&body=\(urlSafeBody)") {
print(url)
WKExtension.sharedExtension().openSystemURL(url)
}
}
}

private func createBody() -> String? {
let messageBody = "hello test message"
return messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
}

private func createNumbers() -> String {
let numbers = ["(111) 222-3333", "(444) 555-6666"]
var tempArray: [String] = []
numbers.forEach { (number: String) in
tempArray.append(number.digitsOnly())
}

return tempArray.joinWithSeparator(",")
}
}

extension String {
func digitsOnly() -> String{
let stringArray = self.componentsSeparatedByCharactersInSet(
NSCharacterSet.decimalDigitCharacterSet().invertedSet)
let newString = stringArray.joinWithSeparator("")

return newString
}
}

With above said I would recommend against using undocumented Apple features for anything you plan on putting on the App Store for the reasons already mentioned in comments.

Opening iMessage with default body containing a link

You need to escape the content passed into the &body= parameter. You can do this with addingPercentEncoding.

For example:

let body = "Download SomeApp by clicking the link below:\n\nhttps://appsto.re/us/someapp.i"

guard let escapedBody = body.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
return
}

guard let phoneUrl = URL(string: "sms:\(numberTextField.text!)&body=\(escapedBody)") else {
return
}

session.dataTaskWithURL completionHandler never called

The task never completes because it never gets started. You have to manually start the data task using its resume() method.

let urlPath = apiURL + apiVersion + url + "?api_key=" + apiKey
let url = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()

let task = session.dataTaskWithURL(url) { data, response, error in
print("Task completed")
// rest of the function...
}

task.resume()

User-Notification Did Receive Response Method Does not allow me to Pass Updated Variable to UIApplication.shared.open() ?

After some demonstrated time, I am able to clarify this by doing this in the following way.

Firstly, function open(URL) was called before, so there was a need of putting my code in dependant blocks, i-e using IOS GCD (Grand Central Dispatch).

I've created two functions and putted them in dispatch_Group.

Here is my code:

// Function A
func functionA_With_Dispatch(identif: String) -> String
{
dispatch_group.enter()

if identif.contains("sms")
{

var numbersH = ""
var messageH = ""
var schemeHere = ""

var chrArr = Array(identif.characters)
chrArr.removeFirst()
chrArr.removeFirst()
chrArr.removeFirst()

let notifIdentifierSecond = String(chrArr)

var fullNameArr = notifIdentifierSecond.characters.split{$0 == "_"}.map(String.init)

let numbers = fullNameArr[1]
messageH = fullNameArr[2]

numbersH.removeAll()

for c in numbers.characters
{
if c != " "
{
numbersH.append(c)
}

}

print(messageH)
print(numbersH)

// "sms:/open?addresses=1-408-555-1212,1-408-555-2121,1-408-555-1221&body=/*message*/"
//sms:/open?addresses=(555)564-8583&body=/*No Bofy*/
schemeHere = "sms:/open?addresses=1" + numbersH + "&body=" + "Wanted to Inform You!"

//schemeHere1-408-555-1212,1-408-555-2121,1-408-555-1221, = "sms:/open?addresses=542-342-3423,23232323&body=/*No Bofy*/"
//sms:/open?addresses=15555648583&body=Wanted to Inform You!
//Open sms:/open?addresses=1115555648583&body=lllll: true

schemeHere = "sms:/open?addresses=\(numbersH)&body=\(messageH)"

print(schemeHere)
dispatch_group.leave()
return schemeHere
}

dispatch_group.leave()
return "empty"

}

Other function for opening URL.

func open_URL_With_Dispatch(schemeHere : String)
{
dispatch_group.enter()

if let url = URL(string: schemeHere) {
print("Inside URL")
if #available(iOS 10, *) {
print("Now Doing in IOS 10.")
UIApplication.shared.open(url, options: [:],
completionHandler: {
(success) in
print("Open \(schemeHere): \(success)")

self.dispatch_group.leave()
})
} else {
let success = UIApplication.shared.openURL(url)
print("Open \(schemeHere): \(success)")
dispatch_group.leave()
}

}
else
{

print("Inside Scheme!")
print(schemeHere)
dispatch_group.leave()
}

}

Now in userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { }, the work is here.

NOTE: dispatch_group is declared at the top of the viewController.

    dispatch_group = DispatchGroup()

let notifIdentifier = response.notification.request.identifier
self.reloadEasy()
let schemeHere = self.functionA_With_Dispatch(identif: notifIdentifier)

dispatch_group.wait()

/*
switch response.actionIdentifier {
case "action1":

if MFMessageComposeViewController.canSendText() {
print("SMS services are available")
self.sendMessage(recipients: ["243243"], message: "ewhrewuew")

}
else
{
self.showMessage(message: "Can't send sms!")
print("Can't send sms!")
}

default:
if MFMessageComposeViewController.canSendText() {
print("SMS services are available")
self.sendMessage(recipients: ["243243"], message: "ewhrewuew")
}
else
{
self.showMessage(message: "Can't send sms!")
print("Can't send sms!")
}
} // Message Switch

*/

let state: UIApplicationState = UIApplication.shared.applicationState
if state == .active {

self.showMessage(message: "Active")
//let schemeHere = "sms:/open?addresses=1-408-555-1212,1-408-555-2121,1-408-555-1221,92-315-5849537&body=/*message*/"

//self.open(notifIdentifier: notifIdentifier)

self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else if state == .background
{
self.showMessage(message: "Background")

//self.open(notifIdentifier: notifIdentifier)

self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else if state == .inactive
{
self.showMessage(message: "In-Active")
//let schemeHere = "sms:/open?addresses=14085551212,14085552121,14085551221,923155849537&body=/*message*/"

//self.open(notifIdentifier: notifIdentifier)

self.open_URL_With_Dispatch(schemeHere: schemeHere)
}
else
{
self.showMessage(message: "Un-defined State")
//let schemeHere = "sms:/open?addresses=14085551212,14085552121,14085551221,923155849537&body=/*message*/"

//self.open(notifIdentifier: notifIdentifier)

self.open_URL_With_Dispatch(schemeHere: schemeHere)
}

Secondly, I've found one other problem after doing so, where I was passing spaces and newLines in the URL string, but now I'm replacing them in the following way for the whole URL.

                for c in messageHere.characters
{
if c == " "
{
appendedMessage.append("%20")
}
else if c == "\n"
{
appendedMessage.append("%0A")
}
else
{
appendedMessage.append(c)
}
}

Why is my variable returning a nil after being converted to an int?

Even simpler, though slightly a trick, you can use integerValue:

temperatureString.integerValue

Unlike toInt, integerValue will stop converting when it finds a non-digit (it also throws away leading spaces.

If temperatureString is a String (rather than an NSString), you'll need to push it over:

(temperatureString as NSString).integerValue

Passing data to Apple Watch app

This applies to OS 1 only. See below for better answers.

I got it working using your method. I guess there's a couple of things you can check:

1) Are you synchronising the defaults after you set the value:

defaults?.synchronize();
NSLog("%@ ", defaults?.dictionaryRepresentation())

2) Have you enabled the App Group in both your app and your extension?

App Group capability for App Target
App Group capability for Watch Extension Target

3) Are you using the correctly named app group when constructing the NSDefaults? For example, I use:

NSUserDefaults(suiteName: "group.com.brindysoft.MyWatch");

Once all that's set up I run the app, set the value in the defaults, then run the glance target which reads the value from the default and that seems to work!

Sample Image


  1. Still stuck? check your app groups in your apple account


Related Topics



Leave a reply



Submit