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