async void HandleMessage(IMessageEvent message) { try { Android.Util.Log.Info("WearIntegration", "Received Message"); var client = new GoogleApiClient.Builder(this) .AddApi(WearableClass.API) .Build(); var result = client.BlockingConnect(30, Java.Util.Concurrent.TimeUnit.Seconds); if (!result.IsSuccess) { return; } var path = message.Path; try { if (path.StartsWith(TweetsPath)) { var viewModel = new TwitterViewModel(); await viewModel.ExecuteLoadTweetsCommand(); var request = PutDataMapRequest.Create(TweetsPath + "/Answer"); var map = request.DataMap; var tweetMap = new List <DataMap>(); foreach (var tweet in viewModel.Tweets) { var itemMap = new DataMap(); itemMap.PutLong("CreatedAt", tweet.CreatedAt.Ticks); itemMap.PutString("ScreenName", tweet.ScreenName); itemMap.PutString("Text", tweet.Text); tweetMap.Add(itemMap); } map.PutDataMapArrayList("Tweets", tweetMap); map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks); await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest()); } } finally { client.Disconnect(); } } catch (Exception e) { Android.Util.Log.Error("WearIntegration", e.ToString()); } }
private void RequestLocationInternal() { Log.Verbose("UtilityService", actionRequestLocation); if (!Utils.CheckFineLocationPermission(this)) { return; } GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) .AddApi(LocationServices.API) .Build(); // It's OK to use blockingConnect() here as we are running in an // IntentService that executes work on a separate (background) thread. ConnectionResult connectionResult = googleApiClient.BlockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT_S, TimeUnit.Seconds); if (connectionResult.IsSuccess && googleApiClient.IsConnected) { Intent locationUpdatedIntent = new Intent(this, typeof(UtilityService)); locationUpdatedIntent.SetAction(actionLocationUpdated); // Send last known location out first if available var location = LocationServices.FusedLocationApi.GetLastLocation(googleApiClient); if (location != null) { Intent lastLocationIntent = new Intent(locationUpdatedIntent); lastLocationIntent.PutExtra( FusedLocationProviderApi.KeyLocationChanged, location); StartService(lastLocationIntent); } // Request new location var locationRequest = new LocationRequest() .SetPriority(LocationRequest.PriorityBalancedPowerAccuracy); LocationServices.FusedLocationApi.RequestLocationUpdates( googleApiClient, locationRequest, PendingIntent.GetService(this, 0, locationUpdatedIntent, 0)); googleApiClient.Disconnect(); } else { Log.Error("UtilityService", string.Format(Constants.GOOGLE_API_CLIENT_ERROR_MSG, connectionResult.ErrorCode)); } }
/// <summary> /// Clears remote device notifications using the Wearable message API /// </summary> /// <returns>The remote notifications.</returns> private async Task ClearRemoteNotifications() { Log.Verbose("UtilityService", actionClearRemoteNotifications); GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) .AddApi(Android.Gms.Wearable.WearableClass.API) .Build(); // It's OK to use blockingConnect() here as we are running in an // IntentService that executes work on a separate (background) thread. ConnectionResult connectionResult = googleApiClient.BlockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT_S, TimeUnit.Seconds); if (connectionResult.IsSuccess && googleApiClient.IsConnected) { // Loop through all nodes and send a clear notification message foreach (var item in await Utils.GetNodes(googleApiClient)) { await WearableClass.MessageApi.SendMessageAsync(googleApiClient, item, Constants.CLEAR_NOTIFICATIONS_PATH, null); } googleApiClient.Disconnect(); } }
/** * Add geofences using Play Services */ private async void AddGeofencesInternal() { Log.Verbose("UtilityService", actionAddGeoFences); if (!Utils.CheckFineLocationPermission(this)) { return; } GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) .AddApi(LocationServices.API) .Build(); // It's OK to use blockingConnect() here as we are running in an // IntentService that executes work on a separate (background) thread. ConnectionResult connectionResult = googleApiClient.BlockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT_S, TimeUnit.Seconds); if (connectionResult.IsSuccess && googleApiClient.IsConnected) { var pendingIntent = PendingIntent.GetBroadcast( this, 0, new Intent(this, typeof(UtilityReceiver)), 0); //TODO: Move to new api var status = await LocationServices.GeofencingApi.AddGeofencesAsync(googleApiClient, TouristAttractionsHelper.GetGeofenceList(), pendingIntent); googleApiClient.Disconnect(); } else { Log.Error("UtilityService", string.Format(Constants.GOOGLE_API_CLIENT_ERROR_MSG, connectionResult.ErrorCode)); } }
/** * Transfer the required data over to the wearable * @param attractions list of attraction data to transfer over */ private void SendDataToWearable(List <Attraction> attractions) { GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this) .AddApi(WearableClass.API) .Build(); // It's OK to use blockingConnect() here as we are running in an // IntentService that executes work on a separate (background) thread. ConnectionResult connectionResult = googleApiClient.BlockingConnect( Constants.GOOGLE_API_CLIENT_TIMEOUT_S, TimeUnit.Seconds); // Limit attractions to send int count = attractions.Count > Constants.MAX_ATTRACTIONS ? Constants.MAX_ATTRACTIONS : attractions.Count; List <DataMap> attractionsData = new List <DataMap>(count); for (int i = 0; i < count; i++) { Attraction attraction = attractions[i]; Bitmap image = null; Bitmap secondaryImage = null; try { //TODO: // Fetch and resize attraction image bitmap //image = Glide.with(this) // .load(attraction.imageUrl) // .asBitmap() // .diskCacheStrategy(DiskCacheStrategy.SOURCE) // .into(Constants.WEAR_IMAGE_SIZE_PARALLAX_WIDTH, Constants.WEAR_IMAGE_SIZE) // .get(); //secondaryImage = Glide.with(this) // .load(attraction.secondaryImageUrl) // .asBitmap() // .diskCacheStrategy(DiskCacheStrategy.SOURCE) // .into(Constants.WEAR_IMAGE_SIZE_PARALLAX_WIDTH, Constants.WEAR_IMAGE_SIZE) // .get(); } catch (Exception e) { Log.Error("UtilityService", "Exception loading bitmap from network"); } if (image != null && secondaryImage != null) { DataMap attractionData = new DataMap(); string distance = Utils.FormatDistanceBetween( Utils.GetLocation(this), attraction.Location); attractionData.PutString(Constants.EXTRA_TITLE, attraction.Name); attractionData.PutString(Constants.EXTRA_DESCRIPTION, attraction.Description); attractionData.PutDouble( Constants.EXTRA_LOCATION_LAT, attraction.Location.Latitude); attractionData.PutDouble( Constants.EXTRA_LOCATION_LNG, attraction.Location.Longitude); attractionData.PutString(Constants.EXTRA_DISTANCE, distance); attractionData.PutString(Constants.EXTRA_CITY, attraction.City); //TODO: // attractionData.PutAsset(Constants.EXTRA_IMAGE, // Utils.CreateAssetFromBitmap(image)); //attractionData.PutAsset(Constants.EXTRA_IMAGE_SECONDARY, // Utils.CreateAssetFromBitmap(secondaryImage)); attractionsData.Add(attractionData); } } if (connectionResult.IsSuccess && googleApiClient.IsConnected && attractionsData.Count > 0) { PutDataMapRequest dataMap = PutDataMapRequest.Create(Constants.ATTRACTION_PATH); dataMap.DataMap.PutDataMapArrayList(Constants.EXTRA_ATTRACTIONS, attractionsData); //TODO: //dataMap.DataMap.PutLong(Constants.EXTRA_TIMESTAMP, DateTime.Now.ToFileTime); PutDataRequest request = dataMap.AsPutDataRequest(); request.SetUrgent(); //TODO: Async/Await // Send the data over // var result = // WearableClass.DataApi.PutDataItem(googleApiClient, request)); // if (!result.).isSuccess()) { // Log.e(TAG, String.format("Error sending data using DataApi (error code = %d)", // result.getStatus().getStatusCode())); // } //} else { // Log.e(TAG, String.format(Constants.GOOGLE_API_CLIENT_ERROR_MSG, // connectionResult.getErrorCode())); // } googleApiClient.Disconnect(); } }
public override void OnDataChanged(DataEventBuffer eventBuffer) { var events = FreezableUtils.FreezeIterable (eventBuffer); eventBuffer.Close (); var google_api_client = new GoogleApiClient.Builder (this) .AddApi (WearableClass.API) .Build (); var connectionResult = google_api_client.BlockingConnect (Constants.CONNECT_TIMEOUT_MS, TimeUnit.Milliseconds); if (!connectionResult.IsSuccess) { Log.Error (TAG, "QuizListenerService failed to connect to GoogleApiClient."); return; } foreach (var ev in events) { var e = ((Java.Lang.Object)ev).JavaCast<IDataEvent> (); if (e.Type == DataEvent.TypeChanged) { var dataItem = e.DataItem; var dataMap = DataMapItem.FromDataItem (dataItem).DataMap; if (dataMap.GetBoolean (Constants.QUESTION_WAS_ANSWERED) || dataMap.GetBoolean (Constants.QUESTION_WAS_DELETED)) { continue; } string question = dataMap.GetString (Constants.QUESTION); int questionIndex = dataMap.GetInt (Constants.QUESTION_INDEX); int questionNum = questionIndex + 1; string[] answers = dataMap.GetStringArray (Constants.ANSWERS); int correctAnswerIndex = dataMap.GetInt (Constants.CORRECT_ANSWER_INDEX); Intent deleteOperation = new Intent (this, typeof(DeleteQuestionService)); deleteOperation.SetData (dataItem.Uri); PendingIntent deleteIntent = PendingIntent.GetService (this, 0, deleteOperation, PendingIntentFlags.UpdateCurrent); //first page of notification contains question as Big Text. var bigTextStyle = new Notification.BigTextStyle () .SetBigContentTitle (GetString (Resource.String.question, questionNum)) .BigText (question); var builder = new Notification.Builder (this) .SetStyle (bigTextStyle) .SetSmallIcon (Resource.Drawable.ic_launcher) .SetLocalOnly (true) .SetDeleteIntent (deleteIntent); //add answers as actions var wearableOptions = new Notification.WearableExtender (); for (int i = 0; i < answers.Length; i++) { Notification answerPage = new Notification.Builder (this) .SetContentTitle (question) .SetContentText (answers [i]) .Extend (new Notification.WearableExtender () .SetContentAction (i)) .Build (); bool correct = (i == correctAnswerIndex); var updateOperation = new Intent (this, typeof(UpdateQuestionService)); //Give each intent a unique action. updateOperation.SetAction ("question_" + questionIndex + "_answer_" + i); updateOperation.SetData (dataItem.Uri); updateOperation.PutExtra (UpdateQuestionService.EXTRA_QUESTION_INDEX, questionIndex); updateOperation.PutExtra (UpdateQuestionService.EXTRA_QUESTION_CORRECT, correct); var updateIntent = PendingIntent.GetService (this, 0, updateOperation, PendingIntentFlags.UpdateCurrent); Notification.Action action = new Notification.Action.Builder ( (int)question_num_to_drawable_id.Get (i), (string)null, updateIntent) .Build (); wearableOptions.AddAction (action).AddPage (answerPage); } builder.Extend (wearableOptions); Notification notification = builder.Build (); ((NotificationManager)GetSystemService (NotificationService)) .Notify (questionIndex, notification); } else if (e.Type == DataEvent.TypeDeleted) { Android.Net.Uri uri = e.DataItem.Uri; //URIs are in the form of "/question/0", "/question/1" etc. //We use the question index as the notification id. int notificationId = Java.Lang.Integer.ParseInt (uri.LastPathSegment); ((NotificationManager)GetSystemService (NotificationService)) .Cancel (notificationId); } ((NotificationManager)GetSystemService (NotificationService)) .Cancel (QUIZ_REPORT_NOTIF_ID); } google_api_client.Disconnect (); }
async void HandleMessage(IMessageEvent message) { try { Android.Util.Log.Info("WearIntegration", "Received Message"); var locationClient = LocationServices.GetFusedLocationProviderClient(this); var client = new GoogleApiClient.Builder(this) .AddApi(WearableClass.API) .Build(); var result = client.BlockingConnect(30, Java.Util.Concurrent.TimeUnit.Seconds); if (!result.IsSuccess) { return; } var path = message.Path; try { var stations = Hubway.Instance.LastStations; if (stations == null) { stations = await Hubway.Instance.GetStations(); } if (path.StartsWith(SearchStationPath)) { if (locationClient == null) { return; } var lastLocation = await locationClient.GetLastLocationAsync(); if (lastLocation == null) { return; } var currentPoint = new GeoPoint { Lat = lastLocation.Latitude, Lon = lastLocation.Longitude }; var nearestStations = Hubway.GetStationsAround(stations, currentPoint, maxItems: 6, minDistance: double.MaxValue); var favManager = FavoriteManager.Obtain(this); var favorites = await favManager.GetFavoriteStationIdsAsync(); var request = PutDataMapRequest.Create(SearchStationPath + "/Answer"); var map = request.DataMap; var stationMap = new List <DataMap> (); foreach (var station in nearestStations) { var itemMap = new DataMap(); itemMap.PutInt("Id", station.Id); var asset = await CreateWearAssetFrom(station); itemMap.PutAsset("Background", asset); string secondary; string primary = StationUtils.CutStationName(station.Name, out secondary); itemMap.PutString("Primary", primary); itemMap.PutString("Secondary", secondary); var distance = GeoUtils.Distance(currentPoint, station.Location); itemMap.PutDouble("Distance", distance); itemMap.PutDouble("Lat", station.Location.Lat); itemMap.PutDouble("Lon", station.Location.Lon); itemMap.PutInt("Bikes", station.BikeCount); itemMap.PutInt("Racks", station.EmptySlotCount); itemMap.PutBoolean("IsFavorite", favorites.Contains(station.Id)); stationMap.Add(itemMap); } map.PutDataMapArrayList("Stations", stationMap); map.PutLong("UpdatedAt", DateTime.UtcNow.Ticks); await WearableClass.DataApi.PutDataItem(client, request.AsPutDataRequest()); } else { var uri = new Uri("wear://watch" + path); var query = uri.GetComponents(UriComponents.Query, UriFormat.Unescaped); var parts = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped).Split('/'); var action = parts[parts.Length - 2]; var id = int.Parse(parts.Last()); if (action == FavoriteAction) { var favorites = FavoriteManager.Obtain(this); handler.Post(() => { if (query == "add") { favorites.AddToFavorite(id); } else { favorites.RemoveFromFavorite(id); } }); } } } finally { client.Disconnect(); } } catch (Exception e) { Android.Util.Log.Error("WearIntegration", e.ToString()); AnalyticsHelper.LogException("WearIntegration", e); } }
public override void OnDataChanged(DataEventBuffer eventBuffer) { var events = FreezableUtils.FreezeIterable(eventBuffer); eventBuffer.Close(); var google_api_client = new GoogleApiClient.Builder(this) .AddApi(WearableClass.API) .Build(); var connectionResult = google_api_client.BlockingConnect(Constants.CONNECT_TIMEOUT_MS, TimeUnit.Milliseconds); if (!connectionResult.IsSuccess) { Log.Error(TAG, "QuizListenerService failed to connect to GoogleApiClient."); return; } foreach (var ev in events) { var e = ((Java.Lang.Object)ev).JavaCast <IDataEvent> (); if (e.Type == DataEvent.TypeChanged) { var dataItem = e.DataItem; var dataMap = DataMapItem.FromDataItem(dataItem).DataMap; if (dataMap.GetBoolean(Constants.QUESTION_WAS_ANSWERED) || dataMap.GetBoolean(Constants.QUESTION_WAS_DELETED)) { continue; } string question = dataMap.GetString(Constants.QUESTION); int questionIndex = dataMap.GetInt(Constants.QUESTION_INDEX); int questionNum = questionIndex + 1; string[] answers = dataMap.GetStringArray(Constants.ANSWERS); int correctAnswerIndex = dataMap.GetInt(Constants.CORRECT_ANSWER_INDEX); Intent deleteOperation = new Intent(this, typeof(DeleteQuestionService)); deleteOperation.SetData(dataItem.Uri); PendingIntent deleteIntent = PendingIntent.GetService(this, 0, deleteOperation, PendingIntentFlags.UpdateCurrent); //first page of notification contains question as Big Text. var bigTextStyle = new Notification.BigTextStyle() .SetBigContentTitle(GetString(Resource.String.question, questionNum)) .BigText(question); var builder = new Notification.Builder(this) .SetStyle(bigTextStyle) .SetSmallIcon(Resource.Drawable.ic_launcher) .SetLocalOnly(true) .SetDeleteIntent(deleteIntent); //add answers as actions var wearableOptions = new Notification.WearableExtender(); for (int i = 0; i < answers.Length; i++) { Notification answerPage = new Notification.Builder(this) .SetContentTitle(question) .SetContentText(answers [i]) .Extend(new Notification.WearableExtender() .SetContentAction(i)) .Build(); bool correct = (i == correctAnswerIndex); var updateOperation = new Intent(this, typeof(UpdateQuestionService)); //Give each intent a unique action. updateOperation.SetAction("question_" + questionIndex + "_answer_" + i); updateOperation.SetData(dataItem.Uri); updateOperation.PutExtra(UpdateQuestionService.EXTRA_QUESTION_INDEX, questionIndex); updateOperation.PutExtra(UpdateQuestionService.EXTRA_QUESTION_CORRECT, correct); var updateIntent = PendingIntent.GetService(this, 0, updateOperation, PendingIntentFlags.UpdateCurrent); Notification.Action action = new Notification.Action.Builder( (int)question_num_to_drawable_id.Get(i), (string)null, updateIntent) .Build(); wearableOptions.AddAction(action).AddPage(answerPage); } builder.Extend(wearableOptions); Notification notification = builder.Build(); ((NotificationManager)GetSystemService(NotificationService)) .Notify(questionIndex, notification); } else if (e.Type == DataEvent.TypeDeleted) { Android.Net.Uri uri = e.DataItem.Uri; //URIs are in the form of "/question/0", "/question/1" etc. //We use the question index as the notification id. int notificationId = Java.Lang.Integer.ParseInt(uri.LastPathSegment); ((NotificationManager)GetSystemService(NotificationService)) .Cancel(notificationId); } ((NotificationManager)GetSystemService(NotificationService)) .Cancel(QUIZ_REPORT_NOTIF_ID); } google_api_client.Disconnect(); }