I have sent data from mobile to wear as
private static final String IMAGE_PATH = "/image";
private static final String IMAGE_TITLE = "imageTitle";
private static final String IMAGE_TO_SEND = "image";
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(IMAGE_PATH);
putDataMapRequest.getDataMap().putString(IMAGE_TITLE, "hi this handheld");
PutDataRequest putDataRequest = putDataMapRequest.asPutDataRequest();
putDataRequest.setUrgent();
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(#NonNull DataApi.DataItemResult dataItemResult) {
if (dataItemResult.getStatus().isSuccess()) {
} else {
}
}
});
On wear side I want to first check if data has been already sent or not. If data has been sent already then I want to use that data otherwise I want to request data for mobile:
I have done it but it always fails. My code is as follow:
Wearable.NodeApi.getLocalNode(googleApiClient).setResultCallback(new ResultCallback<NodeApi.GetLocalNodeResult>() {
#Override
public void onResult(#NonNull NodeApi.GetLocalNodeResult getLocalNodeResult) {
Uri uri = new Uri.Builder()
.scheme(PutDataRequest.WEAR_URI_SCHEME)
.path(IMAGE_PATH)
.authority(getLocalNodeResult.getNode().getId())
.build();
Wearable.DataApi.getDataItem(googleApiClient, uri).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(#NonNull DataApi.DataItemResult dataItemResult) {
if (dataItemResult.getStatus().isSuccess() && dataItemResult.getDataItem() != null) {
Log.d(TAG, "onResult: success result");
DataMap dataMap = DataMap.fromByteArray(dataItemResult.getDataItem().getData());
} else {
}
}
});
}
});
I found solution. I was checking data by getting local nodes id ,so that it was providing null data.Local Node id i-e id of my watch, Node Id must be id of node which has sent data using Data Layer Api. In my case at first my handheld sends data through the Data Layer Api and my watch checks data exist or not.If data found gets data otherwise send request to Handheld.
Wearable.NodeApi.getConnectedNodes(googleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult nodes) {
for (Node node : nodes.getNodes()) {
connectedNode = node;
}
Uri uri = new Uri.Builder()
.scheme(PutDataRequest.WEAR_URI_SCHEME)
.path(IMAGE_PATH)
.authority(connectedNode.getId()) //id which has sent data
.build();
Wearable.DataApi.getDataItem(googleApiClient, uri).setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(#NonNull DataApi.DataItemResult dataItemResult) {
if (dataItemResult.getStatus().isSuccess() && dataItemResult.getDataItem() != null) {
Log.d(TAG, "onResult: successfully got previous data");
} else {
makeRequestToSendData();
Log.d(TAG, "onResult: failed to got previous data");//request handheld to get data using **Message API**
}
}
});
}
});
We have to change getLocalNode to getConnectedNodes .
Your code looks fine, is the node id non null ?
Does it fail at the getDataItem result callback ?
To get the DataMap from the DataItemResult, use this code :
DataItem dataItem = dataItemResult.getDataItem();
if (dataItem != null) {
DataMap dataMap = DataMapItem.fromDataItem(dataItem).getDataMap();
}
Related
Receiving and opening notifications with the app in the background increments the number of Data sent.
In addition the notification is not showing when the app is killed or when it is in the foreground.
Below is my code, the source code is from Gerald Versluis https://github.com/jfversluis/XFFCMPushNotificationsSample
using System;
using Xamarin.Forms;
using Plugin.FirebasePushNotification;
using Xamarin.Forms.Xaml;
namespace FCMTest
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
CrossFirebasePushNotification.Current.Subscribe("all");
CrossFirebasePushNotification.Current.OnTokenRefresh += Current_OnTokenRefresh;
CrossFirebasePushNotification.Current.OnNotificationReceived += Current_OnNotificationReceived;
CrossFirebasePushNotification.Current.OnNotificationOpened += Current_OnNotificationOpened;
//CrossFirebasePushNotification.Current.OnNotificationAction += Current_OnNotificationAction;
}
private void Current_OnTokenRefresh(object source, FirebasePushNotificationTokenEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"Token from function OnTokenRefresh: {e.Token}");
}
private void Current_OnNotificationReceived(object source, FirebasePushNotificationDataEventArgs d)
{
System.Diagnostics.Debug.WriteLine("Received");
foreach (var data in d.Data)
{
System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
}
}
/*private void Current_OnNotificationAction(object source, FirebasePushNotificationResponseEventArgs d)
{
System.Diagnostics.Debug.WriteLine("Opened");
foreach (var data in d.Data)
{
System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
}
}*/
private void Current_OnNotificationOpened(object source, FirebasePushNotificationResponseEventArgs d)
{
System.Diagnostics.Debug.WriteLine("Opened");
foreach (var data in d.Data)
{
System.Diagnostics.Debug.WriteLine($"{data.Key} : {data.Value}");
}
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
using System;
using System.Collections.Generic;
namespace FCMDispatcher
{
class Program
{
static void Main(string[] args)
{
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile("fcm-test-98fe5-firebase-adminsdk-oknwc-c290af4ff0.json")
});
// This registration token comes from the client FCM SDKs.
var registrationToken = "d8yECxIhJXQ:APA91bFGXSrnUVcP07TlN4HpvfstWwEdPQaj4wr6Z3Q-7JqcJJjrFy9LkWdlfzcCNDrZeVy55IDTWxvp5Gfyv8318uRRmIPo6Gp2IQnyUDSHqGLdTF8RMmlwyaECTKWDnmhClMLV8In9";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{"myData", "One more try to say Succeded!"},
},
Token = registrationToken,
//Topic = "all",
Notification = new Notification()
{
Title = "Test from code",
Body = "Here is your test!"
}
};
// Send a message to the device corresponding to the provided
// registration token.
string response = FirebaseMessaging.DefaultInstance.SendAsync(message).Result;
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
}
}
}
Try adding priority with high or max to your Data Payload.
Data = new Dictionary<string, string>()
{
{"myData", "One more try to say Succeded!"},
{"priority", "high"},
},
This complex condition must match to show your notification:
https://github.com/CrossGeeks/FirebasePushNotificationPlugin/blob/d86266a9f45687b418f5f1e69c348681d1ff6e27/Plugin.FirebasePushNotification/DefaultPushNotificationHandler.android.cs#L151
I have a WebService that is working and receiving files using the POST method, but in which I also need to receive data, simultaneously.
ASP.NET WebApi code:
public Task<HttpResponseMessage> Post()
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
string file1 = provider.FileData.First().LocalFileName;
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
And the client, developed for Android, is sending the file and the data like this (the send of the file is tested and working, the sending of the data is still not tested, as I need it to be working in the server side):
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Sample Text Content"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"file\"; filename=\"" + fileName + ".png\""),
RequestBody.create(MEDIA_TYPE_PNG, bitmapdata))
.addFormDataPart("fullpath", "test")
.build();
final com.squareup.okhttp.Request request = new com.squareup.okhttp.Request.Builder()
.url(url)
.post(requestBody)
.build();
How can I change the server to read not only the file but also the data?
Can any one help?
Thanks in advance.
The client in this case android is sending additional values in the body like media_type_png. I had to do something similar however the client was angular and not a mobile app, after some searching back then I found code from the following stackoverflow. Which resulted in the code below.
First receive the incoming message and check that you can process it i.e. [IsMimeMultipartContent][1]()
[HttpPost]
public async Task<HttpResponseMessage> Upload()
{
// Here we just check if we can support this
if (!Request.Content.IsMimeMultipartContent())
{
this.Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
// This is where we unpack the values
var provider = new MultipartFormDataMemoryStreamProvider();
var result = await Request.Content.ReadAsMultipartAsync(provider);
// From the form data we can extract any additional information Here the DTO is any object you want to define
AttachmentInformationDto attachmentInformation = (AttachmentInformationDto)GetFormData(result);
// For each file uploaded
foreach (KeyValuePair<string, Stream> file in provider.FileStreams)
{
string fileName = file.Key;
// Read the data from the file
byte[] data = ReadFully(file.Value);
// Save the file or do something with it
}
}
I used this to unpack the data:
// Extracts Request FormatData as a strongly typed model
private object GetFormData(MultipartFormDataMemoryStreamProvider result)
{
if (result.FormData.HasKeys())
{
// Here you can read the keys sent in ie
result.FormData["your key"]
AttachmentInformationDto data = AttachmentInformationDto();
data.ContentType = Uri.UnescapeDataString(result.FormData["ContentType"]); // Additional Keys
data.Description = Uri.UnescapeDataString(result.FormData["Description"]); // Another example
data.Name = Uri.UnescapeDataString(result.FormData["Name"]); // Another example
if (result.FormData["attType"] != null)
{
data.AttachmentType = Uri.UnescapeDataString(result.FormData["attType"]);
}
return data;
}
return null;
}
The MultipartFormDataMemoryStreamProvider is defined as follows:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
namespace YOURNAMESPACE
{
public class MultipartFormDataMemoryStreamProvider : MultipartMemoryStreamProvider
{
private readonly Collection<bool> _isFormData = new Collection<bool>();
private readonly NameValueCollection _formData = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<string, Stream> _fileStreams = new Dictionary<string, Stream>();
public NameValueCollection FormData
{
get { return _formData; }
}
public Dictionary<string, Stream> FileStreams
{
get { return _fileStreams; }
}
public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
if (parent == null)
{
throw new ArgumentNullException("parent");
}
if (headers == null)
{
throw new ArgumentNullException("headers");
}
var contentDisposition = headers.ContentDisposition;
if (contentDisposition == null)
{
throw new InvalidOperationException("Did not find required 'Content-Disposition' header field in MIME multipart body part.");
}
_isFormData.Add(String.IsNullOrEmpty(contentDisposition.FileName));
return base.GetStream(parent, headers);
}
public override async Task ExecutePostProcessingAsync()
{
for (var index = 0; index < Contents.Count; index++)
{
HttpContent formContent = Contents[index];
if (_isFormData[index])
{
// Field
string formFieldName = UnquoteToken(formContent.Headers.ContentDisposition.Name) ?? string.Empty;
string formFieldValue = await formContent.ReadAsStringAsync();
FormData.Add(formFieldName, formFieldValue);
}
else
{
// File
string fileName = UnquoteToken(formContent.Headers.ContentDisposition.FileName);
Stream stream = await formContent.ReadAsStreamAsync();
FileStreams.Add(fileName, stream);
}
}
}
private static string UnquoteToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
return token;
}
if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
{
return token.Substring(1, token.Length - 2);
}
return token;
}
}
}
Is there some way to define 'general' response codes that are applicable for all calls.
Eg all calls can return one of the following:
400 - Bad request
500 - Internal server error (unknown exception occurred)
503 - Service unavailable (maintenance mode)
Instead of copy-pasting the comments and attributes on every end-point it would be nice if I can define it in some central place.
Thanks #HelderSepu indeed IDocumentFilter is the solution
// Swagger config
swagger.DocumentFilter<DefaultFilter>();
internal class DefaultFilter : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
foreach (var item in swaggerDoc.Paths.Values)
{
UpdateItem(item, "400", "Bad or malformed request.");
UpdateItem(item, "500", "Internal server error.");
UpdateItem(item, "503", "Service in maintenance mode.");
}
}
private static void UpdateItem(PathItem item, string key, string description)
{
TrySetValue(item.Get, key, description);
TrySetValue(item.Put, key, description);
}
private static void TrySetValue(Operation op, string key, string description)
{
if ( (op == null) || (op.Responses.ContainsKey(key)) )
{
return;
}
op.Responses.Add(key, new Response
{
Description = description,
});
}
}
For anybody using Swashbuckle 5
//in AddSwaggerGen
c.OperationFilter<GeneralExceptionOperationFilter>();
internal class GeneralExceptionOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Responses.Add("401", new OpenApiResponse() { Description = "Unauthorized" });
operation.Responses.Add("403", new OpenApiResponse() { Description = "Forbidden" });
//Example where we filter on specific HttpMethod and define the return model
var method = context.MethodInfo.GetCustomAttributes(true)
.OfType<HttpMethodAttribute>()
.Single();
if (method is HttpDeleteAttribute || method is HttpPostAttribute || method is HttpPatchAttribute || method is HttpPutAttribute)
{
operation.Responses.Add("409", new OpenApiResponse()
{
Description = "Conflict",
Content = new Dictionary<string, OpenApiMediaType>()
{
["application/json"] = new OpenApiMediaType
{
Schema = context.SchemaGenerator.GenerateSchema(typeof(string), context.SchemaRepository)
}
}
});
}
}
}
I have a Web API, When the incoming request is not valid then the API sends back a HttpStatusCode.BadRequest and API would also add a CorrelationId into Response's HttpHeader. Something like below
public class ValidateRequestAttribute : ActionFilterAttribute
{
public ValidateRequestAttribute()
{
}
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid == false)
{
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.HttpContext.Response.Headers.Add("x-correlationid", "someid");
context.Result = new ContentResult()
{
Content = "bad request."
};
}
}
}
On client side im using HttpClient to access the API. I am not sure how client would retrieve HttpStatusCode and HttpHeader here. Here is my client code
public bool Process(url)
{
bool result = false;
try
{
Task.Run(async () => await _httpClient.GetStringAsync(url).ConfigureAwait(false)).Result;
}
catch (Exception ex)
{
if(ex is AggregateException)
{
var aggregateException = ex as AggregateException;
foreach(var innerException in aggregateException.InnerExceptions)
{
if (innerException is HttpRequestException)
{
var httpRequestException = innerException as HttpRequestException;
// how do i get StatusCode and HttpHeader values here??
}
}
}
}
return result;
}
I have already gone through SO post here and MSDN article here and also Stephen Cleary's article here
Even though its recommended to make async all the way down, I this case Client and API are both disconnected from each other and client is synchronous. Note that Client's Process method is synchronous method.
Like this:
public bool Process(string url)
{
var result = _httpClient.GetAsync(url).ConfigureAwait(false).GetAwaiter().GetResult();
if (result.StatusCode == HttpStatusCode.BadRequest)
{
IEnumerable<string> values;
if (result.Headers.TryGetValues("x-correlationid", out values))
{
// Should print out "someid"
Console.WriteLine(values.First());
}
}
return result.IsSuccessStatusCode;
}
Also note that doing .GetAwaiter().GetResult(); vs .Result; is recommended since it makes the code easier to work with because it does not throw an AggregateException.
If you want to read the response content as a string just do:
var content = result.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
If you want to make your code async though you should use the async/await keyword and skip the .GetAwaiter().GetResult();.
i use Wicket.Ajax.ajax in pair with AbstractDefaultAjaxBehavior to sent some javascript calculated data to the java. But after event has fired from javascript and comes to Java, browser has been redirected to callback url.
...web/product/1?7&6-1.IBehaviorListener.0-idsPanelPlace%3Floggged_id=332797
logggedidAjax = new AbstractDefaultAjaxBehavior() {
#Override
protected void respond(AjaxRequestTarget target) {
StringValue loggged_vkid = getRequest().getQueryParameters().getParameterValue("loggged_id");
String loggedId = (loggged_id != null) ? loggged_id.toString() : "null";
logger.info("ajax has comming with logged ID " + loggedId);
}
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
String componentMarkupId = getMarkupId();
Map<String, Object> map = new HashMap<>();
map.put("callbackUrl", logggedidAjax.getCallbackUrl());
PackageTextTemplate ptt = new PackageTextTemplate(VKIDsPanel.class, "id_callback.js");
OnDomReadyHeaderItem onDomReadyHeaderItem = OnDomReadyHeaderItem.forScript(ptt.asString(map));
response.render(onDomReadyHeaderItem);
}
};
add(logggedidAjax);
As for js code -
var wcall = Wicket.Ajax.ajax({ u: '${callbackUrl}' + '?loggged_id='+ response.session.mid });
Why browser redirected to the url, since it is Ajax? How to prevent redirection?
I'm not sure what's going wrong in your code, but the following should be easier:
logggedidAjax = new AjaxEventBehavior("domready") {
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
String loggedId = "return {'logged_id': response.session.mid}";
attributes.getDynamicExtraParameters().add(loggedId);
}
#Override
protected void onEvent(AjaxRequestTarget target) {
StringValue loggged_vkid = getRequest().getQueryParameters().getParameterValue("loggged_id");
String loggedId = (loggged_id != null) ? loggged_id.toString() : "null";
logger.info("ajax has comming with logged ID " + loggedId);
}
};
add(logggedidAjax);