Esempio n. 1
0
        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 ();
        }
Esempio n. 7
0
        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);
            }
        }
Esempio n. 8
0
        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();
        }