I'm trying to implement Firebase Topic Messaging in an Android application, and I'm attempting to build a HTTP post request, and I'm receiving a response code of 400. I have looked at various solutions but none of them have seemed to help.
Here is where I call the subclass of AsyncTask:
try{new FirebaseSendMessage().execute("Hello world");}
catch (Exception e) {
Log.d("Exception", e.toString());
}
Here is my Async Task class's subclass.
class FirebaseSendMessage extends AsyncTask<String, Integer, Double> {
private final static String USER_AGENT = "Mozilla/5.0";
private final static String AUTH_KEY = "<My firebase authorization key obtained from firebase>";
private Exception exception;
protected Double doInBackground(String... params) {
try {
sendRequest(params);
} catch (Exception e) {
this.exception = e;
}
return null;
}
protected void onPostExecute(Long l) {
// TODO: check this.exception
// TODO: do something with the feed
}
public void sendRequest(String... params) {
try {
String urlString = "https://fcm.googleapis.com/fcm/send";
URL url = new URL(urlString);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Authorization", "key=" + AUTH_KEY);
String postJsonData = "{\"to\": \"/topics/news\"\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}";
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(postJsonData);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("POST Response Code :: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK){
System.out.println("succeeded");
}
/*InputStream is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//con.disconnect();*/
}
catch(IOException e){
Log.d("exception thrown: ", e.toString());
}
}
}
Error: I/System.out: POST Response Code :: 400
Please let me know if there are additional code snippets required to help me debug. Thanks in advance!
Error 400 means an Invalid JSON in your request:
Check that the JSON message is properly formatted and contains valid fields (for instance, making sure the right data type is passed in).
In your sendRequest, you missed a comma (,) between "news\" and \"data\" and a closing bracket (}):
String postJsonData = "{\"to\": \"/topics/news\"\"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}";
which looks like this:
{"to": "/topics/news/""data":{"message":"...."}
Should be:
String postJsonData = "{\"to\": \"/topics/news\", \"data\": {\"message\": \"This is a Firebase Cloud Messaging Topic Message!\"}}";
So that the JSON structure would be correct:
{"to": "/topics/news/",
"data":{"message":"..."}
}
For those who are willing to use the authentication key in your application.
I suggest to encrypt the key manually by the SHA-1 of your application and the decrypt it at the time of runtime with the SHA-1 code.
Related
I've got a requirement to log message from the Android client. Is there any sumo logic API to log message from the Android application?
You can post your log message/ any message from your Android application to Summo Logic cloud-based log management.
Summo Logic provides Web Services/ REST to perform POST, GET Request.
You just need to post your data on the request body and mention your
Sumo collection endpoint as well as UniqueHTTPCollectorCode.
REST Service/ Web Service : https://[SumoEndpoint]/receiver/v1/http/[UniqueHTTPCollectorCode]
For Instance:
"https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/SanTC12dhaV1oma90Vvb..."
You can use Retorfit / Volley library for REST Communication .
I have given a below pseudo code which conveys the basic REST Communication in background through Android Async Task.
I strictly recommend to use the above mentioned libraries.
public static String performPostRequest(String summoUrl, String payload,
Context context) throws IOException {
URL url = new URL(summoUrl);
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
String line;
StringBuffer jsonString = new StringBuffer();
uc.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
uc.setRequestMethod("POST");
uc.setDoInput(true);
uc.setInstanceFollowRedirects(false);
uc.connect();
OutputStreamWriter writer = new OutputStreamWriter(uc.getOutputStream(), "UTF-8");
writer.write(payload);
writer.close();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while((line = br.readLine()) != null){
jsonString.append(line);
}
br.close();
} catch (Exception ex) {
ex.printStackTrace();
}
uc.disconnect();
return jsonString.toString();
}
Async task
new AsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... params) {
try {
String response = makePostRequest(""https://endpoint1.collection.us2.sumologic.com/receiver/v1/http/ZaVnC4dhaV1oma90Vvb..."",
// Sample JSON Data "
{ \"organization": \"organization.name\",
\"environment": \"environment.name\",
\"apiProduct": \("apiproduct.name"),
\"proxyName": \("apiproxy.name"),
\"appName": \("developer.app.name"),
\"verb": \("request.verb"),
\"url": '' + \("client.scheme") + '://' + \("request.header.host") + \("request.uri"),
\"responseCode": \("message.status.code"),
\"responseReason": \("message.reason.phrase"),
\"clientLatency": total_client_time,
\"targetLatency": total_target_time,
\"totalLatency": total_request_time
}", getApplicationContext());
// Hard coded Success as response from Server, replace with this as per your need
return "Success";
} catch (IOException exception) {
exception.printStackTrace();
return exception.getMessage();
}
}
}.execute("");
For more information, Please refer the documentation from Official Sumo Webpage
https://help.sumologic.com/Send-Data/Sources/02Sources-for-Hosted-Collectors/HTTP-Source/Upload-Data-to-an-HTTP-Source
I want to register a device with my Wordpress plugin. For this the Plguin uses the following code.
Sample request for new registration:
POST /pnfw/register/ HTTP/1.1
Host: yoursite
Content-Length: 26
Content-Type: application/x-www-form-urlencoded
token=new_device_id&os=iOS
Returns:
200 OK: on success.
401 Unauthorized: if OAuth is enabled but the signature is invalid (see below).
404 Not Found: if prevToken is not found on updating registration.
500 Internal Server Error: on missing mandatory parameters, unknown operating system, or general failure.
On errors:
On errors, besides the HTTP status codes defined above, a JSON is returned with this format:
This is the class the device registers with Firebase.
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
private static final String REG_TOKEN = "REG_TOKEN";
#Override
public void onTokenRefresh() {
String recent_token = FirebaseInstanceId.getInstance().getToken();
Log.d(REG_TOKEN,recent_token);
sendRegistrationToServer(recent_token);
}
public void sendRegistrationToServer(String recent_token) {
}
}
I can not get the data from "recent_token" to my server.
I tried the whole day.
public void sendRegistrationToServer(String recent_token) throws IOException {
String result = null;
HttpURLConnection urlConnection = null;
try {
String postData = "token=" + recent_token + "&os=Android";
byte[] postDataBytes = postData.getBytes("UTF-8");
URL url = new URL("http://www.bluestarfish.de/pnfw/register/");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(30000);
urlConnection.setReadTimeout(30000);
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("POST", "/pnfw/register/ HTTP/1.1");
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("charset", "UTF-8");
urlConnection.setRequestProperty("Host", "www.bluestarfish.de");
urlConnection.setRequestProperty("Content-Length", Integer.toString(postDataBytes.length));
OutputStream out = urlConnection.getOutputStream();
out.write(postDataBytes);
out.close();
//result = readStream(urlConnection.getInputStream());
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
//return result;
}
Where is the failure
Unfortunately, nothing happens. Can someone explain the mistake to me?
I've been checking around for some time, but still can't find information on this how exactly to connect my android app to the Github API. I had it registered, had a token as well, read about the endpoints and everything, but cannot understand where the token to be used. May somebody give me a hint?
I've used below code to connect to GitHub Search Repo API in my android app.
//Method 1: To Authorize API access for all HTTP call
//Uncomment this part of code and input your username and password
// Authenticator.setDefault(new Authenticator() {
// #Override
// protected PasswordAuthentication getPasswordAuthentication() {
// return new PasswordAuthentication("username", "password".toCharArray());
// }
// });
HttpURLConnection urlConnection;
URL url;
InputStream inputStream;
try{
url = new URL("https://api.github.com/search/repositories?q="+"searchText");
urlConnection = (HttpURLConnection) url.openConnection();
//Method 2: To Authorize API access while making HTTP request
//Uncomment this part of code and input your username and password
// String basicAuth = "Basic "+Base64.encodeToString("username:password".getBytes(), Base64.NO_WRAP);
// urlConnection.setRequestProperty ("Authorization", basicAuth);
//set request type
urlConnection.setRequestMethod("GET");
//if you uncomment the following line GitHub API will not respond
// urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.connect();
//check for HTTP response
int httpStatus = urlConnection.getResponseCode();
//if HTTP response is 200 i.e. HTTP_OK read inputstream else read errorstream
if (httpStatus != HttpURLConnection.HTTP_OK) {
inputStream = urlConnection.getErrorStream();
//print GitHub api hearder data
Map<String, List<String>> map = urlConnection.getHeaderFields();
System.out.println("Printing Response Header...\n");
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
System.out.println(entry.getKey()
+ " : " + entry.getValue());
}
}
else {
inputStream = urlConnection.getInputStream();
}
//read inputstream
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String temp,response="";
while((temp = bufferedReader.readLine())!=null){
response+=temp;
}
//GitHub api has limit to access over http.
//Api rate limit is 10req/min for unauthenticated user and 30req/min is for authenticated user
boolean apiLimitExceeded = "false";
if(response.contains("API rate limit exceeded")){
apiLimitExceeded =true;
}else {
//convert data string into JSONObject
JSONObject obj = (JSONObject) new JSONTokener(response).nextValue();
JSONArray items = obj.getJSONArray("items");
//total result count and result status
total_count = obj.getString("total_count");
incomplete_results = obj.getString("incomplete_results");
}
urlConnection.disconnect();
} catch (MalformedURLException | ProtocolException | JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Check out my GitHub project to get a complete idea on how to use GitHub search repo API in Android App.
Link: https://github.com/kvipul/Search-GitHub-Repo
There are many filters that GitHub API provides. Check out the Documentation of GitHub search API for more details -https://developer.github.com/v3/search/
I have a server using mongodb, mongoose and node.js.
I have implemented some GET and POST methods.
Inside a HTML website, I can post data to the server within an XMLHttpRequest as follows inside javascript:
function postPlantType(base64){
var httpPost = new XMLHttpRequest(),
path = "http://...", // real URL taken out here
header = ('Content-Type','application/json'),
data = JSON.stringify({image:base64});
httpPost.onreadystatechange = function(err) {
if (httpPost.readyState == 4 && httpPost.status == 201){
console.log(httpPost.responseText);
} else {
console.log(err);
}
};
path = "http://..." // real URL taken out here
httpPost.open("POST", path, true);
httpPost.send(data);
}
this works fine. Now I want to create an Android app, making use of such a POST request, but my Code is not working successfully. Here is my Code:
private class PostNewPlantTask extends AsyncTask<String, Integer, String> {
String responseString = "";
int response;
InputStream is = null;
protected String doInBackground(String... urls){
DataOutputStream wr=null;
try {
URL url = new URL(urls[0]); // urls[0] is the url of the http request "http://www..."
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
String json = "{\"image\":\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYE...\"}";
Log.d("json", json.toString());
conn.setRequestProperty("Content-length", json.getBytes().length + "");
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setAllowUserInteraction(false);
OutputStream os = conn.getOutputStream();
os.write( json.getBytes("UTF-8"));
os.close();
// Starts the query
conn.connect();
response = conn.getResponseCode();
if (response >= 200 && response <=399){
is = conn.getInputStream();
} else {
is = conn.getErrorStream();
}
// Convert the InputStream into a string
String contentAsString = readIt(is, 200);
responseString = contentAsString;
conn.disconnect();
} catch (Exception e) {
responseString = "error occured: "+e;
} finally {
if (is != null){
try { is.close();} catch (Exception e) {Log.d("HTTP POST planttypes","Exception occured at closing InputStream: "+e);}
}
}
Log.d("HTTP POST plants", "The response is: " + response + responseString);
return responseString;
}
protected void onPostExecute(String result){
// TODO: nothing(?)
// give user feedback(?)
}
}
NOTE: If I change the json String to invalid json content e.g. deleting the last "}", The response of the server is
400 "code":"InvalidContent","message":"Invalid JSON: Unexpected end of input"
So I assume the entire json string must be correct, if its unchanged.
I am hardcoding the base64encoded image String here instead of encode a real image, because of testing issues. You can see the image at this jsfiddle.
If I see it correctly, its the exact same request as done from my javascript, but I get 500 internal server error.
However, in order to get more information, here is the server function, that is called for that request url:
function postNewPlantType(req, res, next){
var json = JSON.parse(req.body);
newPlantTypeData = {
image:json.image
};
var imageBuffer = decodeBase64Image(json.image);
newPlantType = new Planttype(newPlantTypeData);
newPlantType.save(function(err){
if (err) return next(new restify.InvalidArgumentError(JSON.stringify(err.errors)));
var fileName = cfg.imageFolder + "" + newPlantType._id + '.jpeg';
fs.writeFile(fileName, imageBuffer.data, function(error){
if (error) log.debug(error);
log.debug("PlantType-ImageFile successfully created on server.");
});
res.send(201, newPlantType);
log.debug("PlantType successfully saved in database.");
});
}
What I am wondering about is, the javascript request is working, but the android request is not. So I assume there must be a mistake in my android code. Can you help me and explain, what the error is and what I have to change?
You probably need to encode it properly:
conn.connect();
DataOutputStream printout = new DataOutputStream(conn.getOutputStream ());
printout.write(URLEncoder.encode(json.toString(),"UTF-8"));
printout.flush ();
printout.close ();
response = conn.getResponseCode();
...
After lots of days of investigation I finally got a 201 response by changing the line
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
to
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
Well.. I was sending an encoded JSON and not a json itself...
My project is targeted to SDK 23, and from now on, as far as I know, I have to use HttpURLConnection instead of HttpClient to make post requests, but I keep getting 501 response code from my webservice (I'm pretty sure it's fully functional, I have no doubt) when making post requests to store users in a remote mysql database. Here follows the main connection code:
class DatabaseConnector extends AsyncTask<String, Void, String> {
private final String CONNECTION_URL = "webservice_address";
#Override
protected String doInBackground(String... params) {
String response = "initial value";
try {
URL url = new URL(CONNECTION_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setUseCaches(false);
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setReadTimeout(10000);
con.setConnectTimeout(15000);
con.setRequestMethod("POST");
JSONObject json = new JSONObject();
json.put("query", params[0]);
JSONObject conn = new JSONObject();
conn.put("database", "database");
conn.put("hostname", "hostname");
conn.put("password", "password");
conn.put("username", "username");
conn.put("port", "port");
json.put("conn", conn.toString());
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(json.toString());
wr.flush();
wr.close();
con.connect();
//display what returns the POST request
StringBuilder sb = new StringBuilder();
int HttpResult = con.getResponseCode();
System.out.println("Response CODE: "+ con.getResponseCode());
if (HttpResult == HttpURLConnection.HTTP_OK) {
System.out.println("Passed1");
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
while ((response = br.readLine()) != null) {
sb.append(response + "\n");
}
br.close();
System.out.println("E: " + sb.toString());
response = sb.toString();
} else {
System.out.println("E2: "+con.getResponseMessage());
response = "Error1: "+con.getResponseMessage();
}
} catch (Exception e) {
response = "Error2: "+e.toString();
}
return response;
}
}
And in my fragment I make the network calls:
try {
String result = new DatabaseConnector().execute("SELECssT 1").get();
Toast.makeText(ContentActivity.this, "Result: "+result, Toast.LENGTH_LONG).show();
} catch (Exception ex) {
Toast.makeText(ContentActivity.this, "Error3: "+ex.toString(), Toast.LENGTH_LONG).show();
}
Nevermind that wrong sql statement, it's meant to be like that, I want the webservice to echo back that syntax error. I have tried many stuff, codes, examples, but it doesn't seem to work.
The point is: I keep getting error code 501 Not Implemented. Why? And how can I fix that?
EDIT:
Any tips or comments on how to improve the way I make network calls on android is welcome, I'm pretty new to that. I'm using a Async call but somehow it's still executing in the main thread, cause the debugger complains:
09-25 19:17:32.714 28853-28853/br.com.developer.package I/Choreographer﹕ Skipped 80 frames! The application may be doing too much work on its main thread.
Thank you all.