Post not yet marked as solved
Hi,
I am currently building a companion watch application and I use wcsession to exchanges some data within the IOS app and watchOS app. I want to know how much time maximum it would take to send a message and receive a response? Because we can't hold the user infinitely until the watch receives the necessary data? So is it handled from the wcsession itself, like sending out a timeout exception or is it necessary to handle from the developer end? If it is can anyone add a possible solution. Thanks.
Post not yet marked as solved
Hi, I am building a companion watch os app and I want to check before sending a message from watch to phone, whether the app is installed on phone. But whenever I check for whether the companion app is installed it always returns true, even when I uninstall the mobile application (Please note this is a dependant app).
Next I found out that in independant apps, watchconnectivity supports isCompanionAppInstalled, and then I ticked the extension to run as independant and then used the isCompanionAppInstalled. It always returns false regardless of whether the app is installed or not? I am not sure why this not working for either of the above 2 scenarios? How can we find whether the companion IOS app is installed in the device from the watch?
Post not yet marked as solved
Hi,
I am developing a dependant watch app and need to pass some data from the phone to watch and vice versa to sync up(Imagine login credentials). So is it secure to pass data as plain text from the mobile to watch app and vice versa? Can hackers or middleman can listen and gain the data within the communication process? Or is the data encrypted by any means default by apple?
I am building an IOS app and it communicates with the JS. So the communication between the two ends must be encrypted. So my main intention is to encrypt from Javascript side and send it to the IOS app mobile end, and the mobile app should decrypt the data. This is how I have done on Javascript side and it works fine as expected,
const key = CryptoJS.enc.Utf8.parse("1111111111111111");
const iv = CryptoJS.enc.Utf8.parse("ui09ji884uh88984");
var encrypted = CryptoJS.AES.encrypt("Hello world",key, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: iv
});
console.log("Encrypted data ="+encrypted);
The issue is how I can decrypt this encrypted data in swift using CommonCrypto. Since this is plain base64 text how can we feed it to decryption? The code I have done so far in swift is posted below,
func testCrypt(data data:[UInt8], keyData:[UInt8], ivData:[UInt8], operation:Int) -> [UInt8]? {
let cryptLength = size_t(data.count+kCCBlockSizeAES128)
var cryptData = [UInt8](repeating: 0, count:cryptLength)
let keyLength = size_t(kCCKeySizeAES128)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(CCOperation(operation),
algoritm,
options,
keyData,
keyLength,
ivData,
data,
data.count,
&cryptData,
cryptLength,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
// cryptData.remove
cryptData.removeSubrange(numBytesEncrypted..<cryptData.count)
} else {
print("Error: \(cryptStatus)")
}
return cryptData;
}
This is the way I have called the above method,
let message = "HEY"
let messageData = Array(message.utf8)
let keyData = Array("1111111111111111".utf8)
let ivData = Array("ui09ji884uh88984".utf8)
let str = "SJeOvypKWad9GzUD2GHRig=="
let buf: [UInt8] = Array(str.utf8)
print("BUFF: ",buf)
let encryptedData = testCrypt(data:messageData, keyData:keyData, ivData:ivData, operation:kCCEncrypt)!
let decryptedData = testCrypt(data:buf, keyData:keyData, ivData:ivData, operation:kCCDecrypt)!
var decrypted = String(bytes:decryptedData, encoding:String.Encoding.utf8)!
This works fine if we do both the encryption and decryption and passing the encrypted byte array for decryption. But when I try to convert the encrypted text in to a byte array and passing it to it, an exception occurs. And also the one which I convert (eg: buf) and which the testCrypt returns after encrypting (eg: encryptedData) isn't similar. Please can anyone elaborate this and provide a solution will be greatly appreciated.
Post not yet marked as solved
Hi, I have created a watch only app and would need to convert it to a dependant watch app since I need to exchange data via watch connectivity? How can we convert such kind of an app? Is it possible without creating a new app, by only changing the required settings in the existing app?
Post not yet marked as solved
Basically i had an existing project developed using swift 5.
I integrated watch app, and developed it using swift UI.
Now i have followed all the required steps , even followed apple documentation, but i am getting connectivity issues between my watch app and ios app.I have created the session successfully , when i send a message form watch app to ios app, it send successfully , but when i send a message from ios app to watch app, i get the error "WCSession counterpart app not installed".
I have verified and cross checked all the below items
bundle identifiers are correctly placed
Supports running without IOS App installation is also unchecked.
Session is activated successfully
I am activating the session in App delegate in applicationDidFinishLaunchingWithOptions on IOS App and in onAppear function of my watch app main class
I have even tried creating a new project with the same configurations like my main project, i created a dummy app using swift and added a Swift UI watch extension just like i did in my main project. The catch is i am not facing any connectivity issue in this dummy app, watch and ios app are communicating perfectly, i can receive the message successfully on both the devices using the same lines of code which i use ion my main project.
I would really appreciate if someone can help me in this, i have tried almost all the solutions and wasted almost a month on this issue.
I have attached my WCSession Manager code
WCSession Manager
Here are the snippets of my code
App Delegate
WatchSessionManager.sharedManager.startSession()
Watch App
import SwiftUI
@main
struct AmbitBoxApp: App {
@SceneBuilder var body: some Scene {
WindowGroup {
NavigationView {
HomeView()
}
.onAppear {
WatchSessionManager.sharedManager.startSession()
}
}
WKNotificationScene(controller: NotificationController.self, category: "myCategory")
}
}
Post not yet marked as solved
Hey there,
I am new to Swift, Objective C, however have a reasonable amount of experience in other programming languages.
Want to get some thoughts on where to begin for an app idea I have. I want to build a WatchOS app that vibrates to a metronome. However, the catch is, I need it to be synchronised to a Digital Audio Workstation (Ableton Live) running on a Macbook.
A bit of background on the use-case. I play in a band, and we run backing tracks on a MacBook. In order for the band to play in time to the backing tracks, we are all fed metronome clicks in our ears. I want to be able to feel the metronome on my apple watch instead.
I was thinking about hooking into the IAC driver. In my DAW software, sending midi notes (that's the metronome) to an IAC driver channel, and feeding that through to the Apple Watch to vibrate each time a midi note is detected.
Obviously, this would need to have as little latency as possible because we all need to play in sync. Some of us may still be on in-ears, so audible metronome clicks and the watch vibrations need to be completely in sync.
Anyway, I am confident in going off and researching and developing the many individual components of this build, but I just need some guidance about my solution design and whether something like this is even possible.
Many thanks!
Post not yet marked as solved
I'm new to Apple watch mainly because I am trying to develop a companion app. New as a user and a developer for Apple Watch.
I'm following an official Apple tutorial, but it seems to make a lot of assumptions.
App groups
Complications (horrible choice of terminology?)
In the "Update Current Complications from iOS apps" step, I have no idea how to do what it's saying.
https://developer.apple.com/documentation/watchconnectivity/using_watch_connectivity_to_communicate_between_your_apple_watch_app_and_iphone_app
How do I choose a "Modular" watch face? What constitutes a "Modular" watch face?
I deep pressed the current (default) face and it went into an edit mode, but swiping right didn't do anything. Swiping left offered more options, but I don't think it aligns with what it's saying to do.
Stuck at 1 & 2
Stuck at 1 & 2
Post not yet marked as solved
The ios side cannot accept the data sent by the watchOS side
// watch os InterfaceController
import WatchKit
import Foundation
import WatchConnectivity
class InterfaceController: WKInterfaceController, WCSessionDelegate {
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
}
@IBOutlet var label: WKInterfaceLabel!
@IBOutlet var button: WKInterfaceButton!
override func awake(withContext context: Any?) {
// Configure interface objects here.
super.awake(withContext: context)
if(WCSession.isSupported()){
let session = WCSession.default;
session.delegate = self;
session.activate();
}
label.setText("")
// button.setTitle("Send Data")
}
@IBAction func sendData() {
print("send data")
let session = WCSession.default;
if(session.isReachable){
DispatchQueue.main.async {
print("Sending data from watch...")
session.transferUserInfo(["method": "sendDataToFlutter"])
}
}else{
print("App not reachable...")
}
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
super.didDeactivate()
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
self.label.setText(message["message"] as! String)
}
}
// AppDelegate.h
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import <WatchConnectivity/WatchConnectivity.h>
@interface WTUserInfoHandler : NSObject <FlutterStreamHandler>
@end
@interface AppDelegate : FlutterAppDelegate<WCSessionDelegate>
@end
// AppDelegate.m
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "Runner-Swift.h"
@implementation WTUserInfoHandler
FlutterEventSink sink;
NSDictionary *info;
- (void) updateUserInfo:(nonnull NSDictionary<NSString *, id> *)userInfo{
NSLog(@"Update Recieved");
if(info != userInfo){
info = userInfo;
if(sink!=nil){
sink(@[userInfo]);
}
}
}
- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
NSLog(@"Adding Flutter Listener");
sink = eventSink;
return nil;
}
- (FlutterError*)onCancelWithArguments:(id)arguments {
NSLog(@"Removing Flutter Listener");
if(sink!=nil){
sink = nil;
}
return nil;
}
@end
@interface AppDelegate ()
@property(nonatomic, strong)WCSession *session;
@property(nonatomic, strong)WTUserInfoHandler* userInfoStreamHandler;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (@available(iOS 10.0, *)) {
[UNUserNotificationCenter currentNotificationCenter].delegate = (id<UNUserNotificationCenterDelegate>) self;
}
[GeneratedPluginRegistrant registerWithRegistry:self];
[self initFlutterMethodChannelWatchSession];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
# pragma mark -----------------WCSessionDelegate start------------------------
-(void) initFlutterMethodChannelWatchSession {
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel *tipinfoChannel = [FlutterMethodChannel
methodChannelWithName:@"com.upcwangying.apps.flutter.boilerplate"
binaryMessenger: controller];
[tipinfoChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
// activate Session
if([@"initWatchSession" isEqualToString:call.method]){
[self activateSession];
result(@"WatchTips Activated");
}else if([@"sendDataToWatch" isEqualToString:call.method]){
[self sendDataToWatch: call.arguments];
} else {
result(FlutterMethodNotImplemented);;
}
}];
}
- (void)sendDataToWatch:(NSString *) data {
if (self.session != nil) {
if (self.session.isPaired && self.session.isReachable) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.session sendMessage:@{@"message": data} replyHandler: nil errorHandler: nil];
});
}
}
}
- (void)session:(WCSession *)session activationDidCompleteWithState:(WCSessionActivationState)activationState error:(nullable NSError *)error {
}
/** ------------------------- iOS App State For Watch ------------------------ */
/** Called when the session can no longer be used to modify or add any new transfers and, all interactive messages will be cancelled, but delegate callbacks for background transfers can still occur. This will happen when the selected watch is being changed. */
- (void)sessionDidBecomeInactive:(WCSession *)session {
}
/** Called when all delegate callbacks for the previously selected watch has occurred. The session can be re-activated for the now selected watch using activateSession. */
- (void)sessionDidDeactivate:(WCSession *)session {}
// Event triggered when userInfo Rxd
- (void)session:(nonnull WCSession *)session didReceiveUserInfo:(nonnull NSDictionary<NSString *, id> *)userInfo
{
if(self.userInfoStreamHandler != nil){
[self.userInfoStreamHandler updateUserInfo:userInfo];
}
}
// Method used to enable the Watch session
- (void)activateSession
{
[self activateChannel];
[self watchSession];
}
// create our eventChannel
-(FlutterEventChannel *) activateChannel {
self.userInfoStreamHandler = [[WTUserInfoHandler alloc] init];
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;
FlutterEventChannel *eventChannel = [FlutterEventChannel eventChannelWithName:@"com.upcwangying.apps.flutter.boilerplate/watchdata" binaryMessenger:controller];
[eventChannel setStreamHandler:(NSObject<FlutterStreamHandler> * _Nullable) self.userInfoStreamHandler ];
return eventChannel;
}
// activate session
- (WCSession *)watchSession
{
if (self.session == nil) {
if ([WCSession isSupported]) {
self.session = [WCSession defaultSession];
[self.session setDelegate:self];
[self.session activateSession];
} else {
NSLog(@"Error - Watch Connectivity NOT supported");
}
}
return self.session;
}
- (void)dealloc
{
if (self.session != nil) {
[self.session setDelegate:nil];
}
}
# pragma mark -----------------WCSessionDelegate end------------------------
@end
Post not yet marked as solved
confirguration nécessaire pour utiliser apple watch se gps cellular: IOS 15 ou IOS 14 (jai 1 Iphone 6s plus et IOS 14.86)
merci
Post not yet marked as solved
I have a watch app which communicates with the iPhone app fine. But when running the WCSession from the Intent extension (used for Siri) I'm getting following in the console logs:
Error Domain=WCErrorDomain Code=7018 "Companion app is not installed."
Can the Watch Intent extension communicate with iPhone app - if so how can I enable it?
Post not yet marked as solved
I am using WatchConnectivity to send messages between my swift iPhone / watch app.
When I receive a message on the iPhone, from the watch, I need to jump to the main thread.
The problem is; when the iPhone is in an inactive/not running state it never seems to complete that action.
The iPhone receives the message, but when it tries to dispatchQueue.main.async{} , it seems to time out. The code inside .async{} never gets called.
Here’s the code where it receives the message on the iPhone:
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
print("Message recieved: ", message)
// We always make it to at least here, no matter what state the application is in.
DispatchQueue.main.async {
// This code is never called if the app is in an inactive/not running state.
// Do something...
}
}
Post not yet marked as solved
I developed an independent Apple Watch that can access network resources on its own using NSURLSession without going through the iPhone. This works fine if the iPhone is on, but if I turn the iPhone off it is not able to connect. Why does my app lose network connectivity when the iPhone is off even though it's a standalone app and the Watch is connected to my WIFI? Is there anything special I need to do to get this working? It appears that no apps work with the internet when the iPhone is off. WIFI is enabled and connected to my WIFI network under the Settings on the watch
Post not yet marked as solved
I have a app want to add watch extension,use WatchConnectivity is success when watch and phone all active,but it is fail when watch inactive.
how to do phone can send message success or trigger watch shock when watch inactive
Post not yet marked as solved
How receive data background if app not Running?
Hell, I need recive data from iPhone to my app in Apple Watch background if apple Watch app not running.
in extension Delegate
I use these func
session(_ session: WCSession, didReceiveMessage message: [String : Any])
and
session(_ session: WCSession, didReceiveMessageData messageData: Data, replyHandler: @escaping (Data) -> Void)
if app on Apple Watch data not received.
I’m new to IOS development, and have spent the last month learning the development environment and the framework. I was able to successfully create a phone app with Xcode 13 that communicates with an autopilot I designed and built for my boat. It communicates with a BLE peripheral designed into the autopilot. All well, and good. The phone app includes a map and and allows for placing custom annotations on the map marking the location of fish I catch, or shallow spots on the lake.
I decided it would be handy to have a watch app that would contain a few controls such as Lock onto the current heading, and turn left and right 10 degrees. Those functions are already implemented on the phone app, so I though it would be a simple task to send a message to the phone to activate those functions.
For the life of me I can’t figure out how to send messages between the two apps.
I backed up and created a simple phone app with a companion watch app. Same problem, no clue how to make them talk.
I’ve searched online, but all the tutorials are way more complicated than what I need, and I can’t ferret the functionality I’m looking for from any of them.
Can someone point me in the right direction to get started?
Or if it’s not too involved, explain how to setup the link between the two apps.
Post not yet marked as solved
I am successfully transferring a .mov file and the correct delegate is being called from the watch counterpart. Yet when I try to reference the URL of the file that was transferred, the file is can’t be found. Is there a specific file path that transferred files are saved to?
Is there another way I can download a .mov file from my iPhone device to a counterpart?
Post not yet marked as solved
Hi there,
I am trying to transfer EventKit Data like EKCalendars / EKEvents / EKReminder from iOS to watchOS via WatchConnectivity.
The connection works but I cannot push these objects directly in response. I also cannot use NSKeyedArchiver since EKCalendars (example) are not able to get converted to Data.
So, any Idea how I can transfer simple EventKit Data from iOS to watchOS?
An addtional hint: I am already fetching these data within watchOS (so no solution) but if the device has an MDM profile it cannot fetch anything but the holiday calendar so I just wanted to test if the iPhone can fetch more (since the MDM profile is stored on iPhone, not on watch) but I can't transfer these data trough WatchConnectivity.
Any hints would be nice – cannot be as hard as I think.
Thanks!
Post not yet marked as solved
I am having problems on Xcode13.3.1, Monterey 12.2.1, Apple M1 Max.
Sending an UpdateApplicationContext update from a paired iPhone simulator is not received on the paired Apple Watch Simulator in the didRecieveApplicationContext. However, sendMessage from the apple watch simulator does update the iphone simulator app properly. It is however, not possible to send anything from the paired iPhone simulator to the paired Apple Watch Simulator.
When working with actual devices everything works properly with WatchConnectivity with passing information back and forth via updateapplicationcontext and sendmessage calls.
Can anyone confirm this is a bug or if there is something wrong with my setup?
Post not yet marked as solved
I created a pair of fairly simple apps (iOS and watchOS) that send messages to each other. It uses the WatchConnectiivity framework. When I run the two apps in the Simulator, I can send messages from the phone to the watch, but I cannot send messages from the watch to the phone. When I attempt that I get the message "Companion app is not installed".
I've seen suggestions that I need to uncheck the "Supports Running Without iOS App Installation" checkbox, but when I do that, the iOS app no longer runs in the Simulator.
My code is here: https://github.com/mvolkmann/watch-with-ios. I'd love to get some hints about how to work past this.