Error with sending PushNotifications with OneSignal android - java

I am working on a Messaging Android App. Users should be notified with a push notification.
At the time I have this code:
public void notifyUser(String user_id, String message) {
try {
OneSignal.postNotification(new JSONObject("{'contents': {'en':['" + message + "']}, " +
"'include_player_ids': ['" + user_id + "'], " +
"'headings': {'en': 'Tag sub Title HI {{user_name}}'}, " +
"'data': {'openURL': 'https://imgur.com'}," +
"'buttons':[{'id': 'id1', 'text': 'Go to GreenActivity'}, {'id':'id2', 'text': 'Go to MainActivity'}]}"),
new OneSignal.PostNotificationResponseHandler() {
#Override
public void onSuccess(JSONObject response) {
Log.d("LOL", "postNotification Success: " + response.toString());
}
#Override
public void onFailure(JSONObject response) {
Log.d("LOL", "postNotification Failure: " + response.toString());
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
But I get an Error in Log:
D/LOL: postNotification Failure: {"errors":["Notification contents for each language must be a string"]}
I searched threw the Internet but didn't find a solution for my Problem.
I hope you can help me...
Thanks in advance.

I believe the error you're seeing is because you're sending up the message inside an array when it should just be a string.
"{'contents': {'en':['" + message + "']} should be "{'contents': {'en':'" + message + "'} (removed the brackets).

Related

Send push notification using Java Springboot server and Expo React native client

My serser uses Java with SpringBoot and my client is an expo react native app which uses typescript.
I am really blocked by this feature: I want to sens push notifications. I tried a lot of methods, but I didn't succeed.
On the client side I am using the method described in expo documentation: https://docs.expo.dev/push-notifications/overview/.
When I use their tool to send test notifications(https://expo.dev/notifications), I receive them on my device.
I didn't manage to send notifications from my client app. I tried all I found on the Inthernet. When I used FirebaseMessagingService and I used the server key from the firebase project as token, I received the SENDER_ID_MISMATCH error.
#Service
public class FirebaseMessagingService {
private final FirebaseMessaging firebaseMessaging;
public FirebaseMessagingService(FirebaseMessaging firebaseMessaging) {
this.firebaseMessaging = firebaseMessaging;
}
public String sendNotification(Note note, String topic) throws FirebaseMessagingException {
Notification notification = Notification
.builder()
.setTitle(note.getSubject())
.setBody(note.getContent())
.setImage(note.getImage())
.build();
Message message = Message
.builder()
.setNotification(notification)
.putAllData(note.getData())
.setToken(topic)
.build();
return firebaseMessaging.send(message);
}
}
I also found the expo-server-sdk-java but I couldn't manage to integrate it.
Any heeeeelp, pleaseeee?
not sure if it's the best practice but it works fine for me.
My pom
<dependency>
<groupId>io.github.jav</groupId>
<artifactId>expo-server-sdk</artifactId>
<version>1.1.0</version>
</dependency>
Then in the java class
private static void sendPushNotification(String token, String titulo, String mensaje, Map<String, Object> data) throws PushClientException {
if (!PushClient.isExponentPushToken(token)) throw new Error("Token:" + token + " is not a valid token.");
ExpoPushMessage expoPushMessage = new ExpoPushMessage();
expoPushMessage.getTo().add(token);
expoPushMessage.setTitle(titulo);
expoPushMessage.setBody(mensaje);
expoPushMessage.setData(data);
List<ExpoPushMessage> expoPushMessages = new ArrayList<>();
expoPushMessages.add(expoPushMessage);
PushClient client = new PushClient();
List<List<ExpoPushMessage>> chunks = client.chunkPushNotifications(expoPushMessages);
List<CompletableFuture<List<ExpoPushTicket>>> messageRepliesFutures = new ArrayList<>();
for (List<ExpoPushMessage> chunk : chunks) {
messageRepliesFutures.add(client.sendPushNotificationsAsync(chunk));
}
// Wait for each completable future to finish
List<ExpoPushTicket> allTickets = new ArrayList<>();
for (CompletableFuture<List<ExpoPushTicket>> messageReplyFuture : messageRepliesFutures) {
try {
allTickets.addAll(messageReplyFuture.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
List<ExpoPushMessageTicketPair<ExpoPushMessage>> zippedMessagesTickets = client.zipMessagesTickets(expoPushMessages, allTickets);
List<ExpoPushMessageTicketPair<ExpoPushMessage>> okTicketMessages = client.filterAllSuccessfulMessages(zippedMessagesTickets);
String okTicketMessagesString = okTicketMessages.stream().map(p -> "Title: " + p.message.getTitle() + ", Id:" + p.ticket.getId()).collect(Collectors.joining(","));
LOGGER.info("Recieved OK ticket for " + okTicketMessages.size() + " messages: " + okTicketMessagesString);
List<ExpoPushMessageTicketPair<ExpoPushMessage>> errorTicketMessages = client.filterAllMessagesWithError(zippedMessagesTickets);
String errorTicketMessagesString = errorTicketMessages.stream().map(p -> "Title: " + p.message.getTitle() + ", Error: " + p.ticket.getDetails().getError()).collect(Collectors.joining(","));
LOGGER.error("Recieved ERROR ticket for " + errorTicketMessages.size() + " messages: " + errorTicketMessagesString);
/**
// Countdown 30s
int wait = 30;
for (int i = wait; i >= 0; i--) {
System.out.print("Waiting for " + wait + " seconds. " + i + "s\r");
Thread.sleep(1000);
}
System.out.println("Fetching reciepts...");
List<String> ticketIds = (client.getTicketIdsFromPairs(okTicketMessages));
CompletableFuture<List<ExpoPushReceipt>> receiptFutures = client.getPushNotificationReceiptsAsync(ticketIds);
List<ExpoPushReceipt> receipts = new ArrayList<>();
try {
receipts = receiptFutures.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
System.out.println("Recieved " + receipts.size() + " receipts:");
for (ExpoPushReceipt reciept : receipts) {
System.out.println("Receipt for id: " + reciept.getId() + " had status: " + reciept.getStatus());
}
*/
}
In the App.js from react native project with EXPO 44 i take expo token in this way
async function registerForPushNotificationsAsync() {
let token;
if (isDevice) {
const { status: existingStatus } =
await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== "granted") {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== "granted") {
alert("Failed to get push token for push notification!");
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
}
if (Platform.OS === "android") {
Notifications.setNotificationChannelAsync("default", {
name: "default",
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: "#FF231F7C",
});
}
return token;
}
effect from App.js
useEffect(() => {
initFirebaseApp();
registerForPushNotificationsAsync().then(async (token) => {
//store in some place token
});
// This listener is fired whenever a notification is received while the app is foregrounded
notificationListener.current =
Notifications.addNotificationReceivedListener(handleNotification);
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
responseListener.current =
Notifications.addNotificationResponseReceivedListener(
handleNotificationResponse
);
return () => {
Notifications.removeNotificationSubscription(
notificationListener.current
);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
notification handlers in App.js
const handleNotification = (response) => {
// console.log(response);
};
const handleNotificationResponse = (response) => {
// console.log(response)
};
I hope this helps you
Docs
Expo SDK documentation
Expo docs reference

Cannot Resolve Symbol "Place.Field"

I am trying to migrate new Auto Complete Place Picker I have updated library from "com.google.android.gms:play-services" to new "com.google.android.libraries.places:places-compat:2.0.0" and implemented SupportPlaceAutocompleteFragment.
All works fine however the error I am getting is:
"Place.Field" Cannot resolve symbol 'Field'
Below is my code:
// Initialize the AutocompleteSupportFragment.
SupportPlaceAutocompleteFragment supportPlaceAutocompleteFragment = (SupportPlaceAutocompleteFragment)getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
//List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
// Specify the types of place data to return.
supportPlaceAutocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
// Set up a PlaceSelectionListener to handle the response.
supportPlaceAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Toast.makeText(MapsActivity.this, "Place: " + place.getName() + ", " + place.getId(), Toast.LENGTH_LONG).show();
Log.i("", "Place: " + place.getName() + ", " + place.getId());
}
#Override
public void onError(Status status) {
}
});
supportPlaceAutocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
Can you help me solve this error:
"Place.Field" Cannot resolve symbol 'Field'
Ensure that you import the correct Place class.
import com.google.android.libraries.places.api.model.Place;
Hope this helps.
The SupportPlaceAutocompleteFragment class is deprecated. Please use the AutocompleteSupportFragment class instead. Refer to Google's migration guide and the Place Autocomplete's guide.
// Initialize the AutocompleteSupportFragment.
AutocompleteSupportFragment supportPlaceAutocompleteFragment = (AutocompleteSupportFragment) getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
//List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
// Specify the types of place data to return.
supportPlaceAutocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
// Set up a PlaceSelectionListener to handle the response.
supportPlaceAutocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
Toast.makeText(MapsActivity.this, "Place: " + place.getName() + ", " + place.getId(), Toast.LENGTH_LONG).show();
Log.i("", "Place: " + place.getName() + ", " + place.getId());
}
#Override
public void onError(Status status) {
}
});
supportPlaceAutocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
Hope this helps!

Parse save ParseGeoPoint by objectId fails with "com.parse.ParseRequest$ParseRequestException:"

Following instructions here to save data to an object by objectId thru android app and getting errmsg com.parse.ParseRequest$ParseRequestException: (without anything following semicolon). I have confirmed objectId is as shown in parse dashboard. Can someone please help me figure out what I'm doing incorrectly? Thanks
final String parseRequest = "Request";
final String parseRequestDriverLocation = "driverLocation";
private void saveDriverLocation(String objectId, Location driverLocation) {
Log.i("saveDriverLocation", "objectId=" + objectId + ", driverLocation=" + driverLocation.toString());
ParseGeoPoint locationDriverParse = new ParseGeoPoint(driverLocation.getLatitude(), driverLocation.getLongitude());
ParseObject acceptedRequest = ParseObject.createWithoutData(parseRequest, objectId);
Log.i("saveDriverLocation", "acceptedRequest=" + acceptedRequest.toString() + "\nlocationDriverParse=" + locationDriverParse.toString());
acceptedRequest.put(parseRequestDriverLocation, locationDriverParse);
acceptedRequest.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("saveDriverLocation", "driver location saved successfully");
} else {
Log.i("saveDriverLocation", "saving driver location failed... " + e.toString());
}
}
});
}
The logcat:
I/saveDriverLocation: objectId=Ddm73yXhPC, driverLocation=Location[gps 41.677770,-80.385998 acc=20 et=+1d7h59m59s883ms alt=18.0 {Bundle[mParcelledData.dataSize=40]}]
I/saveDriverLocation: acceptedRequest=com.parse.ParseObject#ddeb183
locationDriverParse=ParseGeoPoint[41.677770,-80.385998]
I/saveDriverLocation: saving driver location failed... com.parse.ParseRequest$ParseRequestException:
Apparently a Parse class can only have one ParseGeoPoint column! Here is reference.

How to find senders Bitcoin Address in BitcoinJ after receiving a transaction

So in my app I have the following functionality for receiving bitcoins
kit.wallet().addCoinsReceivedEventListener(new WalletCoinsReceivedEventListener() {
#Override
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
txtLog.append("-----> coins resceived: " + tx.getHashAsString() + "\n");
txtLog.append("received: " + tx.getValue(wallet) + "\n");
Futures.addCallback(tx.getConfidence().getDepthFuture(1), new FutureCallback<TransactionConfidence>() {
#Override
public void onSuccess(TransactionConfidence result) {
txtLog.append("\nSuccess! Recieved: " + tx.getValue(wallet) + "\n");
//Find address of sender here
}
#Override
public void onFailure(Throwable t) {
throw new RuntimeException(t);
}
});
}
});
This works great, OnSuccess triggers properly once a transaction is confirmed and added to my wallet. txtLog is just a textArea in my java frame which displays some text output for me. What I need to do now is find the address of the sender at this point, can i do this with the Transaction object tx? Any help would be appreciated.
Found the solution! Unfortunately it uses a depreciated method. I just added the following in the appropriate spot.
String address = "";
for (TransactionInput txin : tx.getInputs()){
address = txin.getFromAddress().toString();
}

Elasticsearch index a document

I'm having serious issues trying to find the correct syntax to push a document into an elasticsearch index by type.
My code im using to do this is :
String url = "https://my_url/my_index_name";
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response).getJSONObject("form");
String site = jsonResponse.getString("site"),
network = jsonResponse.getString("network");
Log.d("Site: ", site + "\nNetwork: "+network);
} catch (JSONException e) {
e.printStackTrace();
Log.e("JSON EXCEPTION", e.toString());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}
)
{
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<>();
// the POST parameters:
params.put("type", "type_name");;
params.put("field1", field1_value);
params.put("field2", field2_value);
params.put("field3", field3_value);
params.put("field4", field4_value);
params.put("field5", field5_value);
return params;
}
};
Volley.newRequestQueue(this).add(postRequest);
It's hitting the server, as I'm getting 400 requests, but I just cant get it to go in using this.
12-14 16:19:04.533 12642-13089/? E/Volley﹕ [41831]
BasicNetwork.performRequest: Unexpected response code 400 for URL
Can some enlighten me as to what the correct syntax is, using java code, or tell me what I'm doing wrong?
I assumed the correct syntax was:
http:// url | index_name | type | body ?
EDIT: I've searched SO, elastic java api's, google groups and all over the internet for 3 days now, with no luck! Anything at all is greatly appreciated !
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.e("VOLLEY ERROR", "" + error.toString());
}
}
Results in : VOLLEY ERROR﹕ com.android.volley.ServerError
Any ideas?
Ok, so I managed to fix it.
There was two issues:
The first issue was with the URL which was:
String url = "https://my_url/my_index_name";
It should have been:
String url = "https://my_url/my_index_name/type%20-d";
The second issue was with the actual arguments:
params.put("type", "type_name");;
params.put("field1", field1_value);
params.put("field2", field2_value);
params.put("field3", field3_value);
params.put("field4", field4_value);
params.put("field5", field5_value);
return params;
I swapped this out for :
String urlParameters =
"{" +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"," +
" \"field\": \" + field_value \"" +
"}";
And post by:
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
Everything is working as I want now, thanks for the help.

Categories