Emojis not rendering properly in iOS push notifications - java

I have a Java Spring Boot web service and I am trying to send push notifications to an iOS device.
The problem I am facing is that the emoji text Which is directly pasted, like
String emoji = "😀";
Or its code, like
String emoji = "\uD83D\uDE0A";
it shows as ? (Question mark symbol)
I have tried getting it as bytes of UTF_8 characters like this:
byte[] emojis = user.getEmoji().getBytes(); //Here user.getEmoji() returns a collection of 2-3 emojis
String emojisAsString = new String(emojis, StandardCharsets.UTF_8);
Integer emojiCodePoint = emojisAsString.codePointAt(emojisAsString.offsetByCodePoints(0,0));
char emojiChars[] = {Character.highSurrogate(emojiCodePoint), Character.lowSurrogate(emojiCodePoint)};
But it still shows as question marks.
I also tried using UTF-8 code like "\xE2\x9A\xA1" but this one just got printed as it is on the notification.
Also when I call the notification API from postman using FCM APIs and paste emojis, it shows emojis in the notification, it just shows as question marks when done through Java web service.
This is the Push notification service code
#RequestMapping(value = "/send", method = RequestMethod.GET, produces = "application/json")
public static ResponseEntity<String> send(String message, String deviceToken, Integer type, Object response, String userNameAsTitle) {
//response.setMessage(message);
//response.setNotificationType(type);
JSONObject body = new JSONObject();
body.put("to", deviceToken);
body.put("priority", "high");
Map<String, Object> map = new HashMap<>();
map.put("title", userNameAsTitle);
map.put("body", message);
//map.put("alert", descprtion);
map.put("type", type);
map.put("badge", 1);
map.put("sound", "default");
map.put("response", response);
JSONObject notification = new JSONObject(map);
//body.put("notification", notification);
body.put("notification", notification);
HttpEntity<String> request = new HttpEntity<>(body.toString());
CompletableFuture<String> pushNotification = androidPushNotificationsService.send(request);
CompletableFuture.allOf(pushNotification).join();
try {
String firebaseResponse = pushNotification.get();
System.out.println(firebaseResponse.toString());
return new ResponseEntity<>(firebaseResponse.toString(), HttpStatus.OK);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
return new ResponseEntity<>("Push Notification ERROR!", HttpStatus.BAD_REQUEST);
}

Related

Generating authentication token for APNS connection

I am new to vertx, and using an app server created via vertx for connection with APNS for push notifications.
I created an authProvider via
private JWTAuth createOauthProvider() {
PubSecKeyOptions pubSecKeyOptions = new PubSecKeyOptions()
.setAlgorithm("ES256").setSecretKey(*/private key from .p8 extracted as is removing unwanted part in base64*/);
return JWTAuth.create(vertx(), new JWTAuthOptions().addPubSecKey(pubSecKeyOptions));
}
and then a JWT via
private String createJwt() {
Instant now = Instant.now();
JsonObject decoded = new JsonObject()
.put("alg", "ES256")
.put("kid", "kid here")
.put("iss", "teamid here")
.put("iat", now.getEpochSecond());
String jwt = oauth2JWTProvider.generateToken(decoded,
new JWTOptions().setAlgorithm("ES256"));
return jwt;
}
Now here's my query -
Is my token creation criteria correct?
JWT created after this when send to APNS returns a 403-InvalidProviderToken.
Appreciate all the help i can get. Thanks!!
Answering my own question as i was able to get around this and just in case it helps anyone else. Just posting the createJwt() method rest everything remains same-
private String createJwt() {
Instant now = Instant.now();
JsonObject header = new JsonObject()
.put(JwtConstants.ALG, "ES256")
.put(JwtConstants.KID, "kid here");
JsonObject payload = new JsonObject()
.put(JwtConstants.ISS, "team id here")
.put(JwtConstants.IAT, now.getEpochSecond());
String jwt = oauth2JWTProvider.generateToken(payload,
new JWTOptions()
.setHeader(header)
.setAlgorithm("ES256"));
return jwt;
}

Axios post request to springboot backend

I'm trying to send a formData post request (using axios) to my backend (springboot) but I'm not sure of the proper way to do it. My plan is to pass the data through the controller to a service that will utilize it.
Axios call -
startStreamLocation() {
const location = new FormData();
location.set("accuracy", this.accuracy)
location.set("lat", this.lat)
location.set("lng", this.lng)
location.set("timeStamp", this.timeStamp)
axios.post("http://localhost:8080/api/v1/location/request-location", location,
{headers: {'Content-Type': 'application/json'}})
},
Controller -
#PostMapping(value = "request-location")
public ResponseEntity<?> requestLocation() {
connectionRequestService.addDataToStream();
return new ResponseEntity<Authenticator.Success>(HttpStatus.OK);
}
Service -
public void addDataToStream() {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonKinesis kinesisClient = AmazonKinesisClient.builder()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(awsRegion)
.build();
PutRecordsRequest putRecordsRequest = new PutRecordsRequest();
putRecordsRequest.setStreamName("location-stream");
List <PutRecordsRequestEntry> putRecordsRequestEntryList = new ArrayList<>();
PutRecordsRequestEntry putRecordsRequestEntry = new PutRecordsRequestEntry();
putRecordsRequestEntry.setData(ByteBuffer.wrap(( INJECT DATA HERE ).getBytes()));
putRecordsRequestEntry.setPartitionKey(String.format("partitionKey-%d"));
putRecordsRequestEntryList.add(putRecordsRequestEntry);
putRecordsRequest.setRecords(putRecordsRequestEntryList);
PutRecordsResult putRecordsResult = kinesisClient.putRecords(putRecordsRequest);
System.out.println("\nData sent successfully... \n" + putRecordsResult);
try {
Thread.sleep(1000);
}
catch (InterruptedException exception) {
throw new RuntimeException(exception);
}
}
Since you want to send form data to the server, you would need to change the Content-Type header in your Axios call to multipart/form-data. This helps the server understand the resource type being sent by the client.
On the server end, you'll want to read this form data. I can think of the following two ways to do that
Use #RequestParam to read individual form keys. For example, if my form data contains a key named Foo, I'd read it on the server end as this
#PostMapping(value = "/form-data")
public void readFormData( #RequestParam(value = "Foo") String foo )
Use #RequestBody to map the form data to a MultiValueMap which can be then read from like a normal map. Here's the code snippet for the same
#PostMapping(value = "/form-data")
public void readFormData( #RequestBody MultiValueMap<String,String> formData )

POST request with JSON body do not deliver to the endpoint in springboot microservice architecture

I'm building my first springboot microservice project and I'm trying to POST a request to a subscriber service, which requires a body in json format and has to include a name and uri for the subscription service to reach the subscriber, this is the class which implement the POST request,
public class Registration{
public static void postRegistration(){
final String registrationUrl = "localhost:9000/registry";
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
JSONObject registrationDetails = new JSONObject();
headers.setContentType(MediaType.APPLICATION_JSON);
registrationDetails.put("name", "OrderGenerator");
registrationDetails.put("uri", "http://localhost:8081/generate");
HttpEntity<String> request =
new HttpEntity<String>(registrationDetails.toString(), headers);
String response = restTemplate.postForObject(registrationUrl,request,String.class);
System.out.println(response);
}
};
i have called that method in the main class as follows as i want it to execute when i start the server,
#SpringBootApplication
public class OrderGeneratorServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderGeneratorServiceApplication.class, args);
Registration.postRegistration();
}
my compiler doesnt, not show any errors but i do not receive notifications to the url i provided, However it starts to work when i send the POST request through postman. What am i doing wrong here?
If you are using Postman, it creates auto generated code for the requests you are making. Its On the right hand side right below the "SAVE" button. You need to create your own auto format method so that you can give the correct input. Here is an example from some API that I am currently consuming.
You see how I have a super long input for the third line? You should create a method that will take your input and auto format it.
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n \"categoryName\": \"PostMan\",\r\n \"categoryQuestions\": [\r\n \"When is the last time you experienced nostalgia?\",\r\n \"What's the scariest dream you've ever had?\",\r\n \"What's the weirdest thought you've ever had?\",\r\n \"What's the first thing that comes to mind when you hear the word fidget?\",\r\n \"What made-up word would you incorporate into the English language if you could?\"\r\n ]\r\n}");
Request request = new Request.Builder()
.url("http://localhost:8080/api/v1/categories")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = client.newCall(request).execute();
System.out.println(response.body().string());
Here is my example (I am working with JSON Data in the format like this
{
"categoryName": "PostMan",
"categoryQuestions": [
"When is the last time you experienced nostalgia?",
"What's the scariest dream you've ever had?",
"What's the weirdest thought you've ever had?",
"What's the first thing that comes to mind when you hear the word fidget?",
"What made-up word would you incorporate into the English language if you could?"
]
}
This is how I formatted that data.
public static String inputParse(String nameInput, ArrayList<String> questionInput) {
String inputBuilder = "{\r\n \"categoryName\": \"" + nameInput + "\",\r\n \"categoryQuestions\": [\r\n ";
for (int i = 0; i < questionInput.size(); i++)
{
inputBuilder += "\"" + questionInput.get(i) + "\"";
if (i != questionInput.size()-1)
{
inputBuilder += ",";
}
}
inputBuilder += "\r\n ]\r\n}";
return inputBuilder;
}
In addition, I see that you are working with Springboot. You can use org.springframework.web.client.RestTemplate (rest-template) to consume rest api. An example for using REST Template that i got from this website.
private void createEmployee() {
Employee newEmployee = new Employee("admin", "admin", "admin#gmail.com");
RestTemplate restTemplate = new RestTemplate();
Employee result = restTemplate.postForObject(CREATE_EMPLOYEE_ENDPOINT_URL, newEmployee, Employee.class);
System.out.println(result);
}

Get last 20 emails from Gmail (Java Android)

How can I get last 20 emails from gmail?
ListMessagesResponse listMessagesResponse = mService.users().messages()
.list(user).setQ("from:----")
.execute();
Currently I am using this but it returns message IDs without any payload. I want to get full email with body. Can it be like get the latest email from specific sender?
As #trajchevska pointed out you can only get the basic details with your code. To get messages in full format you should call mService.users().messages().get(user, messageId).execute() for every message. Best way for this is to create a batch call. So if you want to get all the messages that match specified query you should do something like this.
final ListMessagesResponse response = mService.users().messages().list(user).setQ("from:----").execute();
final List<Message> messages = new ArrayList<Message>();
while (response.getMessages() != null) {
messages.addAll(response.getMessages());
if (response.getNextPageToken() != null) {
String pageToken = response.getNextPageToken();
response = service.users().messages().list(user).setQ("from:----").setPageToken(pageToken).execute();
} else {
break;
}
}
final List<Message> fullMessages = new ArrayList<>();
final JsonBatchCallback<Message> callback = new JsonBatchCallback<Message>() {
public void onSuccess(Message message, HttpHeaders responseHeaders) {
fullMessages.add(message);
}
public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) {
// do what you want if error occurs
}
};
BatchRequest batch = mService.batch();
for (Message message : messages) {
mService.users().messages().get(user, message.getId()).setFormat("full").queue(batch, callback);
}
batch.execute();
Hope this helps.
The list function only returns the list of messages with basic details which is usually the id only. If you want to get the payload or other message details you need to iterate through all messages pulled with list and call the wanted function specifically on the selected object. I only have some basic knowledge in Java, but the logic would be something like this:
messages = listMessagesResponse.getMessages();
for (Message message : messages) {
payload = message.getPayload();
...
}
Check their docs, they have some example that can be helpful.
List Messages
Get Concrete Message

Get & Post image from Android to WCF

i wanna send image along with text from my android client to wcf web service on localhost. i have successfully sent text and received as well and as it was quite difficult for me just to send text but now i have to send image along with text as well. i'd prefer not to change my method like using stream etc. i want to pass image as json and receive it in my web service and store it in sql database image column or even storing on disc would do. So please tell me what changes i need to make in code below to do it.
Thanks in advance...!
here's my AddIssue method of web service.
public int AddIssue(Issue issue)
{
// byte[] bm=System.Convert.FromBase64String(issue.Image.ToString());
//Binary bo = new Binary(bm);
try
{
NorthwindDataContext dc = new NorthwindDataContext();
Issue currentIssue = new Issue
{
Area = issue.Area,
Description= issue.Description,
// Image =bo
};
if (currentIssue == null)
{
// Couldn't find an [Order] record with this ID
return -3;
}
dc.Issues.InsertOnSubmit(currentIssue);
// Update our SQL Server [Order] record, with our new Shipping Details (send from whatever
// app is calling this web service)
dc.SubmitChanges();
return 0; // Success !
}
catch (Exception)
{
return -1;
}
}
and here's my java code. i have tried different codes but none worked. the above two codes work with a C# client but i need it in java i.e android.
JSONObject json = new JSONObject();
json.put("Area",editTextPrice.getText().toString());
json.put("Description",editTextDescription.getText().toString());
img.buildDrawingCache();
Bitmap bm=img.getDrawingCache();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String encodedImage = Base64.encodeToString(b , Base64.DEFAULT);
json.put("Image",encodedImage);
issue class of my web service
namespace JSONWebService
{
[DataContract]
[Serializable]
public class wsIssue
{
[DataMember]
public int IssueId { get; set; }
[DataMember]
public string Area { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public string Image { get; set; }
}
n here's interface of my web service
namespace JSONWebService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "getAllIssues")]
List<wsIssue> GetAllIssues();
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json,RequestFormat = WebMessageFormat.Json, UriTemplate = "AddIssue")]
int AddIssue(Issue issue);
i have tried directly using json.toString() instead of byte but that didn't work either.
I don't know what error you get from android side but you can also try with HttpUrlConnection to send data check this answer.
Or look this answer if you want to use HttpPost:
https://stackoverflow.com/questions/6360207/android-sending-a-byte-array-via-http-post
JSONObject args = new JSONObject();
args.put("Area", editTextPrice.getText().toString());
args.put("Description", editTextDescription.getText().toString())
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); //bm is the bitmap object
byte[] b = baos.toByteArray();
String encodedImage = Base64.encodeToString(b , Base64.DEFAULT);
args.put("image",encodedImage);
//You can also use NameValuePair instead JSON
//like : nameValuePairs.add(new BasicNameValuePair("Area", editTextPrice.getText().toString());
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
nameValuePairs.add(new BasicNameValuePair("data", arg.toString()));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
On C# get image string then change to bytearray
public class Message
{
public string Area {get;set;}
public string Description {get;set;}
public string Image {get;set;}
}
Message message = new JavaScriptSerializer().Deserialize<Message>(result);
byte[] imageData = Convert.FromBase64String(message.image);
MemoryStream ms = new MemoryStream(imageData);
Image returnImage = Image.FromStream(ms);

Categories

Resources