I am trying to create a small application that will read the CPU load of computers / laptops and send a push notification to the browser of my main laptop, which will contain the user name and how much the processor is loaded. As a technology for sending notifications, I chose FCM. The code itself is already ready, but I lack one detail. I need to get the device token of my laptop, to which this push notification will be sent (because as I understand it, the device token is the token of the computer where the notification is sent). But I do not know how to get this token. Most of the guidelines are directed to Android, and I need to send it from computer to computer. Maybe someone can tell me a different approach to sending these notifications, or the option that I attached is also suitable for a start? If so, how can I get this token?
public class MetricTesting {
Process p = Runtime.getRuntime().exec("typeperf \"\\238(_Total)\\6\"");
BufferedReader br = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String line;
double pr = 0;
Pattern pattern = Pattern.compile("[\\d]{0,3}\\.\\d{4,}");
while ((line = br.readLine()) != null) {
System.out.println(line);
Matcher m = pattern.matcher(line);
if (!m.find()) {
continue;
}
line = m.group();
pr = Math.round(Double.parseDouble(line) * 10.0) / 10.0;
System.out.println(pr);
if (pr > 5) {
PushNotificationSender.sendPushNotification("??", Double.toString(pr));
System.out.println(System.getProperty("user.name") + ", Processor loaded " + pr + " %");
}
}
String[] g = br.readLine().split("");
System.out.println(Arrays.toString(g));
br.close();
}
}
class PushNotificationSender {
public final static String AUTH_KEY_FCM = "//";
public final static String API_URL_FCM = "https://fcm.googleapis.com/fcm/send";
public static String sendPushNotification(String deviceToken, String pr)
throws IOException, JSONException {
String result = "";
URL url = new URL(API_URL_FCM);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "key=" + AUTH_KEY_FCM);
conn.setRequestProperty("Content-Type", "application/json");
JSONObject json = new JSONObject();
json.put("to", deviceToken.trim());
JSONObject info = new JSONObject();
info.put("title", "CPU is overloaded");
info.put("body", System.getProperty("user.name")+"\n"+pr);
json.put("notification", info);
try {
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(json.toString());
wr.flush();
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
result = "OK";
} catch (Exception e) {
e.printStackTrace();
result = "BAD";
}
return result;
}
}
You must try https://firebase.google.com/docs/cloud-messaging/js/client to create a web client for firebase push notification.
In the above article, generating firebase token is also mentioned.
You can try to push notification thru topic instead of firebase token as well.
Related
I have been trying all day to get a minecraft plugin to allow players on bedrock edition on my geyser sever to (OPTIONALY) sign in to java edition using OAuth2's device code flow. I successfully can get a code and url but when I go to poll the API for a successful login I get "Cross-origin token redemption is permitted only for the 'Single-Page Application'." I've tried adding SPA to my azure app registration but the issue persists. I've tried setting the origin header in my request to "http://localhost" and the issue persist:
here is my code for retrieving the login token:
public static JSONObject pollSignIn(String deviceCode) {
double i = 0;
long previousTime = 0;
while (i <= 60000 /*GeyserFloodgateSkinFix.defaultConfig.requestTimeout*/) {
while (!(System.currentTimeMillis() > previousTime)) {}
previousTime = System.currentTimeMillis();
i++;
if ((i/1000) % 3 == 0) {
try {
URL url = new URL("https://login.microsoftonline.com/common/oauth2/v2.0/token");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Origin", null);
con.setDoOutput(true);
System.out.println(deviceCode);
String body = String.format(
"grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=%s&device_code=%s",
"[Censored]",
deviceCode
);
byte[] output = body.getBytes(StandardCharsets.UTF_8);
OutputStream os = con.getOutputStream();
os.write(output);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(br.readLine());
}
JSONObject json = new JSONObject(sb.toString());
if (json.getString("token_type").equalsIgnoreCase("Bearer")) {
return json;
}
}
catch (Exception ignored) {
System.out.println(ignored.getMessage());
}
}
}
return null;
}
if it helps heres the code I use to get the token (This works)
public static JSONObject getAuthCode() {
try {
URL url = new URL("https://login.microsoftonline.com/common/oauth2/v2.0/devicecode");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setDoOutput(true);
String body = String.format(
"scope=XboxLive.signin%%20offline_access&client_id=%s",
"[Censored]"
);
OutputStream os = con.getOutputStream();
byte[] output = body.getBytes(StandardCharsets.UTF_8);
os.write(output, 0, output.length);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
con.disconnect();
return new JSONObject(sb.toString());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
UPDATE: I managed to fix the above error but now I am getting "The provided value for the input parameter 'scope' is not valid. The scope 'XboxLive.signin offline_access' is not configured for this tenant." Chanfing the tenant to "consumer" throws "The provided value for the input parameter 'device_code' is not valid. Device codes supporting the personal Microsoft Account sign-in audience can only be used for v2 common or consumers tenants"
The code below shows a method, downloadUrl(), that takes a String, "myurl," its parameter. There are only two possible urls that I ever send to it, and the behavior of the method is different for each.
when myurl = URL1, it uses a GET request and everything works fine.
when myurl = URL2, however, it uses a POST request, and the response from the php page indicates that the post parameters sent with the request were empty. You can see the line where I set the POST params, so I don't understand why it's sending no params?!
Thanks for any help!
-Adam.
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
String response = "";
try {
URL urlObject = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();
// find out if there's a way to incorporate these timeouts into the progress bar
// and what they mean for shitty network situations
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setDoInput(true);
// INSERTED QUICK CHECK TO SEE WHICH URL WE ARE LOADING FROM
// it's important because one is GET, and one is POST
if (myurl.equals(url2)){
Log.i(TAG, "dlurl() in async recognizes we are doing pre-call");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
String postParams = "?phone=" + phone;
writer.write(postParams);
Log.i(TAG, "we're adding " + postParams + "to " + urlObject);
writer.flush();
writer.close();
os.close();
}
else {
conn.setRequestMethod("GET");
conn.connect();
}
// Starts the query
int responseCode = conn.getResponseCode();
Log.i(TAG, "from " + myurl + ", The response code from SERVER is: " + responseCode);
is = conn.getInputStream();
// Convert the InputStream into a string
// i guess we look up how to do this
if (responseCode == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
response += line;
}
} else {
response = "from downloadUrl, php page response was not OK: " + responseCode;
}
// it's good to close these things?
is.close();
conn.disconnect();
Log.i(TAG, "response is " + response);
return response;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
try with following code block to send parameters of the POST request.
Map<String,String> params = new LinkedHashMap<>();
params.put("phone", "phone");
StringBuilder postPraamString = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postPraamString.length() != 0) postPraamString.append('&');
postPraamString.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postPraamString.append('=');
postPraamString.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
writer.write(postDataBytes);
So I figured out the root of the problem...
In the line:
String postParams = "?phone=" + phone;
The problem was that leading question mark. The question mark should only be used in GET requests.
I am trying to validate an Apple App Store receipt from a Java service. I can not get anything back other than an error 21002, "Receipt Data Property Was Malformed". I have read of others with the same problem, but, have not see a solution. I thought this would be fairly straight forward, but, have not been able to get around the error. Here is my code:
EDIT By making the change marked // EDIT below, I now get an exception in the return from the verifyReceipt call, also makred //EDIT:
String hexDataReceiptData = "<30821e3b 06092a86 4886f70d 010702a0 .... >";
// EDIT
hexDataReceiptData = hexDataReceiptData.replace(">", "").replace("<", "");
final String base64EncodedReceiptData = Base64.encode(hexDataReceiptData.getBytes());
JSONObject jsonObject = new JSONObject();
try
{
jsonObject.put("receipt-data",base64EncodedReceiptData);
}
catch (JSONException e)
{
e.printStackTrace();
}
URL url = new URL("https://sandbox.itunes.apple.com/verifyReceipt");
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
//Send request
OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream());
wr.write(jsonObject.toString());
wr.flush();
//Get Response
BufferedReader rd =
new BufferedReader(new
InputStreamReader(connection.getInputStream()));
StringBuilder httpResponse = new StringBuilder();
String line;
while ((line = rd.readLine()) != null)
{
httpResponse.append(line);
httpResponse.append('\r');
}
wr.close();
rd.close();
// EDIT
// {"status":21002, "exception":"java.lang.IllegalArgumentException"}
As posted here: Java and AppStore receipt verification, do the base64 encoding in iOS and send to the server. But, why?
I need to write a server which sends push notifications to iOS and Android devices.
I can successfully send notifications to iOS. Luckily it was painless to implement that part.
I'm facing a problem with the easiest part of the task: Android.
I configured GCM and the Android device successfully registers against the server.
When I try to send a push to the device, I get the following error:
STATUS: 400
JSON_PARSING_ERROR: Unexpected token END OF FILE at position 0.
Here the code that sends the request.
AndroidPush push = new AndroidPush();
push.getRegids().add(token);
push.getData().setMessage(message);
push.getData().setMsgcnt(String.format("%d", (badge + 1)));
URL u = new URL(androidEndpoint);
HttpsURLConnection conn = null;
OutputStream os = null;
OutputStreamWriter osw = null;
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
try{
conn = (HttpsURLConnection)u.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", androidContentType);
conn.setRequestProperty("Authorization", androidAuthorization);
conn.connect();
os = conn.getOutputStream();
osw = new OutputStreamWriter(os);
System.out.println(push.toJSON());
osw.write(push.toJSON());
int status = conn.getResponseCode();
System.err.println("STATUS: "+status);
if(status == 200){
is = conn.getInputStream();
} else {
is = conn.getErrorStream();
}
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String read = null;
do {
read = br.readLine();
if(read != null)
sb.append(read);
} while (read != null);
if(status != 200){
System.err.println(sb.toString());
} else {
System.out.println(sb.toString());
}
} catch(IOException ex) {
ex.printStackTrace();
throw ex;
} finally {
if(isr != null)
isr.close();
if(is != null)
is.close();
if(osw != null)
osw.close();
if(os != null)
os.close();
if(conn != null)
conn.disconnect();
}
Where:
androidEndpoint = "https://android.googleapis.com/gcm/send";
androidContentType = "application/json";
androidAuthorization = "key=<mykey>";
and the output of the push.toJSON() method is the following String:
{
"registration_ids" : ["APA91bEmD8T9NxQj07uhbTAsD1GTWvT7L_no1SXP70YWaQGPX6VO73pdAOa53PN-hyAyy-3erItWxLDb8W1aQ2nh3np0NttJ5g66w2-142d4bXTCsmrF34-J7rWw4IUObutQznaml59XdfweiEGKzv1Otp3quffUEA"],
"data" : {
"message":"Push di prova",
"msgcnt":"13"
}
}
I cannot see anything wrong... What am I missing?
Thank you for your help,
Developing a solution with php, I recieved always the same error WHEN the message had Umlauts (e.g. äöü) in it.
Without the message went through and arrived the reciever.
The solution was finally to utf8_encode( 'your text here äöä' ) your outgoing strings (message, title, etc. whatever).
Cost my at least several hours to detect what was 'wrong'.
Is it the case that you are missing ',' as shown below in bold
{
"registration_ids" : ["APA91bEmD8T9NxQj07uhbTAsD1GTWvT7L_no1SXP70YWaQGPX6VO73pdAOa53PN-hyAyy-3erItWxLDb8W1aQ2nh3np0NttJ5g66w2-142d4bXTCsmrF34-J7rWw4IUObutQznaml59XdfweiEGKzv1Otp3quffUEA"],
"data" : {
"message":"Push di prova",
"msgcnt":"13"**,**
}**,**
}
Refer message given in this link: http://developer.android.com/google/gcm/adv.html#payload
I have a small java app that, given a list of references for google places, must get back the Id's for each of said google places (long story short, we were storing references for places instead of their Id's, and only now realized that references are not unique per place).
My app works perfectly for about 95% of the places in the list, but fails with a "NOT_FOUND" status code for some records. Some investigation reveals that the place reference for these particular places is (when combined with the https://maps.googleapis.com/maps/api/place/details/json?sensor=false&key=myApiKey prefix) about 2 characters too long for a URL. The last couple of characters are getting truncated.
My initial thought was that I would just make a POST request to the google places API, but I'm getting back "REQUEST_DENIED" status code from the google servers when sending the same into as a POST request.
Is there anyway around this, or is this just an emergent bug with the google places API (now that the number of places has pushed the reference too long?).
I should also note that the places that fail are all recently added by our application.
This is what my current (working for 95%) code looks like:
public static JSONObject getPlaceInfo(String reference) throws Exception
{
URL places = new URL("https://maps.googleapis.com/maps/api/place/details/json?sensor=false&key="+apiKey+"&reference="+reference);
URLConnection con = places.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer input = new StringBuffer();
String inputLine;
while ((inputLine = in.readLine()) != null)
input.append(inputLine);
in.close();
JSONObject response = (JSONObject) JSONSerializer.toJSON(input.toString());
return response;
}
and this is what my "ACCESS_DENIED" post code looks like:
public static JSONObject getPlaceInfo(String reference) throws Exception
{
String data = URLEncoder.encode("sensor", "UTF-8") + "=" + URLEncoder.encode("true", "UTF-8");
data += "&" + URLEncoder.encode("key", "UTF-8") + "=" + URLEncoder.encode(apiKey, "UTF-8");
data += "&" + URLEncoder.encode("reference", "UTF-8") + "=" + URLEncoder.encode(reference, "UTF-8");
URL places = new URL("https://maps.googleapis.com/maps/api/place/details/json");
URLConnection con = places.openConnection();
con.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(data);
wr.flush();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer input = new StringBuffer();
String inputLine;
while ((inputLine = in.readLine()) != null)
input.append(inputLine);
in.close();
JSONObject response = (JSONObject) JSONSerializer.toJSON(input.toString());
return response;
}
An example of the reference that fails is:
CnRtAAAAxm0DftH1c5c6-krpWWZTT51uf0rDqCK4jikWV6eGfXlmKxrlsdrhFBOCgWOqChc1Au37inhf8HzjEbRdpMGghYy3dxGt17FEb8ys2CZCLHyC--7Vf1jn-Yn1kfZfzxznTJAbIEg6422q1kRbh0nl1hIQ71tmdOVvhdTfY_LOdbEoahoUnP0SAoOFNkk_KBIvTW30btEwkZs
Thanks in advance!
You're sending your request parameters in the body, which isn't supported by the API. There's a good answer about GET and request params at:
HTTP GET with request body
The following code should work for Place detail requests:
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
private static final String TYPE_DETAILS = "/details";
private static final String OUT_JSON = "/json";
HttpURLConnection conn = null;
StringBuilder jsonResults = new StringBuilder();
try {
StringBuilder sb = new StringBuilder(PLACES_API_BASE);
sb.append(TYPE_DETAILS);
sb.append(OUT_JSON);
sb.append("?sensor=false");
sb.append("&key=" + API_KEY);
sb.append("&reference=" + URLEncoder.encode(reference, "utf8"));
URL url = new URL(sb.toString());
conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
} catch (MalformedURLException e) {
return null;
} catch (IOException e) {
return null;
} finally {
if (conn != null) {
conn.disconnect();
}
}
try {
// Create a JSON object hierarchy from the results
JSONObject jsonObj = new JSONObject(jsonResults.toString()).getJSONObject("result");
jsonObj.getString("name");
} catch (JSONException e) {
Log.e(LOG_TAG, "Error processing JSON results", e);
}