Following this tutorial: https://blog.pusher.com/build-an-android-chat-app-with-pusher/ , I have been debugging for hours to find out why it is not working.
From the client I do the following:
private void postMessage() {
String text = messageInput.getText().toString();
// return if the text is blank
if (text.equals("")) {
return;
}
RequestParams params = new RequestParams();
// set our JSON object
params.put("text", text);
params.put("name", "DogLover69");
params.put("time", new Date().getTime());
// create our HTTP client
AsyncHttpClient client = new AsyncHttpClient();
client.post(MESSAGES_ENDPOINT, params, new JsonHttpResponseHandler(){
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
runOnUiThread(new Runnable() {
#Override
public void run() {
messageInput.setText("");
}
});
}
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
Toast.makeText(
getApplicationContext(),
"Something went wrong :(",
Toast.LENGTH_LONG
).show();
}
});
}
Note: MESSAGES_ENDPOINT is the ip address of the server + the port I'm connecting to, and I have confirmed it is correct.
From the server I do the following:
var Pusher = require('pusher');
var pusher = new Pusher({
appId: "421748",
key: "4e789b8f7019463f945b",
secret: "fff93ef698f9231c00dd"
});
...
app.post('/messages', function(req, res){
var message = {
text: req.body.text,
name: req.body.name
}
console.log(message);
pusher.trigger('messages', 'new_message', message, function(err){
console.log("bananas");
done(err);
});
res.json({success: 200});
});
The server prints the messages correctly and responds with the 200 success code; however, although the server successfully receives the message from the client, the server cannot send the message to pusher. Using the debug console on the pusher website confirms this.
This is triggering the error, so I believe it is the issue:
pusher.trigger('messages', 'new_message', message, function(err){
console.log("bananas");
done(err);
});
Server output when I catch the error from pusher.trigger
I have been trying to figure out whats wrong for a very long time now,
any help would be appreciated. I may try to get in touch with the pusher folks as I have followed the tutorial religiously and triple checked all my steps. There isn't a lot of resources for my particular issue but I have hope others with this issue can find this!
Thanks
The code looks correct. Can you please double check if there's a cluster value associated with it - you should be able to see it on dashboard.pusher.com.
Related
I am relatively new to android development and I have been squeezing my brain juice for hours on probably a very simple error. Look, the app's been working fine yesterday and after I made some changes on some XML files and ran the app on my emulator, I experience this error:
2019-09-10 14:13:19.533 6388-
6516/ E/Volley: [301]
BasicNetwork.performRequest: Unexpected response code 406 for
http://applybpojobs.com/widevalueappfiles/server/api/addvehicle.php
2019-09-10 14:13:21.573 1633-1656/system_process E/memtrack: Couldn't load
memtrack module
I have already tried numerous solutions on the web and it seems not to fix my problem. This is my code:
StringRequest stringRequest = new StringRequest(Request.Method.POST,
URL_ADD_VEHICLE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i(TAG, response.toString());
try {
JSONObject jsonObject = new JSONObject(response);
String Success = jsonObject.getString("success");
if (Success.equals("1")){
hideLoader();
Toast.makeText(Addvehicle.this,"Vehicle Added
Successfully",Toast.LENGTH_SHORT).show();
}else if (Success.equals("0")){
hideLoader();
Toast.makeText(Addvehicle.this,"Vehicle
Already Exist",Toast.LENGTH_SHORT).show();
}
}catch (JSONException e){
e.printStackTrace();
hideLoader();
Toast.makeText(Addvehicle.this,"Vehicle Added
Error"+e.toString(),Toast.LENGTH_SHORT).show();
}
}
},
new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error){
Toast.makeText(Addvehicle.this,"Vehicle Added
Error"+error.toString(),Toast.LENGTH_SHORT).show();
hideLoader();
}
})
I am receiving a blank response from this URL and I need guidance on how to fix this:
http://*********.php
For whatever reasons, this page on my app stopped working because of this error. Any help would be appreciated. Again, I'm basically new in android development so please understand that a simple error like this bleeds my nose.
Here are my server php codes:
<?php
require '../core/connect.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$plate_number=$_POST['plate_number'];
$vin=$_POST['vin'];
$car_make=$_POST['car_make'];
$car_model=$_POST['car_model'];
$car_year=$_POST['car_year'];
$displacement=$_POST['displacement'];
$fuel_type=$_POST['fuel_type'];
$transmission=$_POST['transmission'];
$mileage=$_POST['mileage'];
$owner_name=$_POST['owner_name'];
$address=$_POST['address'];
$phone_number=$_POST['phone_number'];
$email_adress=$_POST['email_adress'];
$facebook=$_POST['facebook'];
$adddate = date("d/m/Y");
$photo = $_POST['photo'];
$id=uniqid();
$path = "vehicle_upload/$id.jpeg";
$finalpath = "*********.$path;
$sql1=mysqli_query($connect,"SELECT * FROM _addvehicle WHERE
PlateNumber='$plate_number'");
if (mysqli_num_rows($sql1) > 0) {
$result['success'] = "0";
$result['message'] = "error";
echo json_encode($result);
}else{
$sql = mysqli_query($connect, "INSERT IGNORE INTO
_addvehicle(PlateNumber, Vin, Make, Model, Year, Displacement, FuelType,
Transmission, Mileage, OwnerorCompany, HomeorCompanyAddress, ContactNumber,
EmailAddress, FacebookID, AddDate, vehicleImage)VALUES('$plate_number','$vin','$car_make','$car_model','$car_year','$displacement','$fuel_type','$transmission','$mileage','$owner_name','$address','$phone_number','$email_adress','$facebook','$adddate','$finalpath')");
if ($sql) {
if (file_put_contents($path, base64_decode($photo))) {
$result['success'] = "1";
$result['message'] = "success";
echo json_encode($result);
//mysqli_close($connect);
}
}
}
}
?>
In POST request you need to send parameters like an empty Hashmap i.e
{"":""} or you need to try https instead of http.
I have asked a similar question but the answer did not help me. I am trying to call a rest service from my android app. The rest service looks like this:
#RestController
#RequestMapping("/login")
public class LoginController {
#ResponseBody
#RequestMapping(value = "/user", method = RequestMethod.GET)
public boolean getUser(#RequestParam(value = "name", required = true) String userName, #RequestParam(value = "password", required = true) String password) {
if (userName.equals("MMM") && password.equals("mmm")) {
return true;
} else {
return false;
}
}
}
I start my REST service and I try to call it from my android app like this:
public void invokeWS(RequestParams params){
AsyncHttpClient client = new AsyncHttpClient();
client.setConnectTimeout(7000);
client.get("https://ipaddress:8080/login/user/",params ,new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
// Hide Progress Dialog
prgDialog.hide();
try {
JSONObject obj = new JSONObject(responseBody.toString());
if(obj.getBoolean("status")){
Toast.makeText(getApplicationContext(), "You are successfully logged in!", Toast.LENGTH_LONG).show();
// Navigate to Home screen
navigatetoHomeActivity();
}
// Else display error message
else{
errorMsg.setText(obj.getString("error_msg"));
Toast.makeText(getApplicationContext(), obj.getString("error_msg"), Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
Toast.makeText(getApplicationContext(), "Error Occured [Server's JSON response might be invalid]!", Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
prgDialog.hide();
if(statusCode == 404){
Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
}
else if(statusCode == 500){
Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
}
// When Http response code other than 404, 500
else{
Toast.makeText(getApplicationContext(), statusCode + "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet or remote server is not up and running]", Toast.LENGTH_LONG).show();
// Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet or remote server is not up and running]", Toast.LENGTH_LONG).show();
}
}
});
}
The status code that I receive is 0.
When I use an API to test the REST service it is OK. I do not get any errors. I am on the same network and the firewall is turned off.
To understand what is going wrong you need to investigate in your "error" object in onFailure method
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.i("ws", "---->>onFailure : " + error);
}
});
SUGGESTIONS:
1) Do not send password in GET!
The password must not be part of the url, please use POST and send the password in the request body
2) Your android code looks good, but it exist a native framework to call REST services called "VOLLEY"
Volley offers the following benefits:
Automatic scheduling of network requests.
Multiple concurrent network connections.
Transparent disk and memory response caching with standard HTTP cache coherence.
Support for request prioritization.
Cancellation request API. You can cancel a single request, or you can set blocks or scopes of requests to cancel.
Ease of customization, for example, for retry and backoff.
Strong ordering that makes it easy to correctly populate your UI with data fetched asynchronously from the network.
Debugging and tracing tools.
the code is not more complex than yours...
EXAMPLE:
String url = "http://my-json-feed";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
mTextView.setText("Response: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
}
});
https://developer.android.com/training/volley/
I can see you are doing a couple of "bad practices" here.
Problem 1
I can see your Spring Controller is wanting a Username and Password as URL parameters. This is a no. A server may log URL/endpoint requests which will now contain your credentials in plain text.
Fix option
Very common -> Use an Authorization header (most common: See Basic Auth) over HTTPS.
Less common -> Pass the username and password in a POST body.
Problem 2
Not using the framework as intended
I'd suggest using Spring Security. It will make your stuff a lot more secure and worth doing in the long run. It will take care of authentication, roles and password hashing all for you.
I successed to send ack to android client from nodejs server but I don't succeed to do reverse. I have this error: Callbacks are not supported when broadcasting at Socket.emit
Serveur nodejs:
socket.broadcast.to(socketid).emit('message', data, callThis);
//this function is executed when client calls it
function callThis (dataFromClient){
console.log("Call back fired: " + dataFromClient);
}
client android:
socket.on("message", new Emitter.Listener() {
#Override
public void call(Object... args) {
Ack ack = (Ack) args[args.length - 1];
ack.call();
JSONObject data = (JSONObject) args[0];
.....
}
}
What can I do to resolve this problem?
Basically support the answer of #Xeoncross. When a connection came, just saved the socket into a map, like below
this.connections = new Map<string, SocketIO.Socket>()
this.server.on("connection", (socket: SocketIO.Socket) => {
this.connections.set(socket.id, socket)
})
Then use a loop to send all users individually
public broadcast(msg: string) {
for(const socket of this.connections.values()) {
socket.emit("block", msg, (confirm: string) => {
console.log("confirmation msg: ", confirm)
})
}
}
As the error says, "Callbacks are not supported when broadcasting". It doesn't look like you are broadcasting though, as you are trying to send to a single client. So assuming socket is an actual client socket instance you can change your code:
socket.broadcast.to(socketid).emit('message', data, callThis);
to just send to that one person
socket.emit('message', data, callThis);
I've been working with android-async-http (http://loopj.com/android-async-http/) lib with android but for some reason I can't catch the response from server, I know that the server receive and do the things that should do, but I can't get the response for no reason.
Here is the method that calls the API:
public User registUser(String mail, String pass) throws UnsupportedEncodingException {
final User user = new User();
user.setToken("enter");
String bodyAsJson = "{\"user\":{\"email\":\""+mail+"\",\"password\":\""+pass+"\"}}";
StringEntity entity = new StringEntity(bodyAsJson);
Header[] headers = {
new BasicHeader("Content-type", "application/json")
};
client.post(this.context, "http://104.131.189.224/api/user", headers , entity, "application/json", new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject json) {
try {
json = json.getJSONObject("user");
user.setId(json.getInt("id"));
user.setEmail(json.getString("email"));
user.setPassword("123456");
user.setToken(json.getString("auth_token"));
} catch ( JSONException e) {
user.setToken("not json");
} catch (Exception e) {
user.setToken("error ");
}
}
#Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
user.setToken("comes json array");
}
#Override
public void onSuccess(int statusCode, Header[] headers, String responseString) {
user.setToken(responseString);
}
#Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
user.setToken("error");
}
#Override
public void onRetry(int retryNo) {
user.setToken("nothing");
}
});
return user;
}
when I call the method, the user.getToken shows only the "enter" that I put in the beginin, that means, never entered in the onSuccess, onFailure, or onRetry methods.
but I know that the server receive my request because the server log shows:
(example: email: carlos#prueba.com, pass: prueba)
"=>"carlos#prueba.com", "password"=>"[FILTERED]"}}
D, [2015-03-17T05:15:27.660562 #28450] DEBUG -- : (0.8ms) BEGIN
D, [2015-03-17T05:15:27.671126 #28450] DEBUG -- : User Exists (2.6ms) SELECT
1 AS one FROM `users` WHERE `users`.`email` = BINARY 'carlos#prueba.com' LIMIT
1
D, [2015-03-17T05:15:27.677448 #28450] DEBUG -- : SQL (1.0ms) INSERT INTO `us
ers` (`email`, `encrypted_password`, `created_at`, `updated_at`) VALUES ('carlos
#prueba.com', '$2a$10$Dg358IzoaG5KVJ8ZJTeViev2v5B9CAnAqIYI1Zd4EIFC.0Mh.nMU6', '2
015-03-17 05:15:27.672898', '2015-03-17 05:15:27.672898')
D, [2015-03-17T05:15:27.681514 #28450] DEBUG -- : (2.0ms) COMMIT
D, [2015-03-17T05:15:27.684634 #28450] DEBUG -- : User Exists (0.6ms) SELECT
1 AS one FROM `users` WHERE `users`.`auth_token` = '6aff3b4162cfcf3062a6db12a1c
ee2bc' LIMIT 1
D, [2015-03-17T05:15:27.685582 #28450] DEBUG -- : (0.2ms) BEGIN
D, [2015-03-17T05:15:27.690901 #28450] DEBUG -- : SQL (0.8ms) UPDATE `users`
SET `auth_token` = '6aff3b4162cfcf3062a6db12a1cee2bc', `updated_at` = '2015-03-1
7 05:15:27.687516' WHERE `users`.`id` = 11
D, [2015-03-17T05:15:27.693809 #28450] DEBUG -- : (1.8ms) COMMIT
I, [2015-03-17T05:15:27.698987 #28450] INFO -- : Rendered api/users/_user.jso
n.jbuilder (0.3ms)
I, [2015-03-17T05:15:27.700292 #28450] INFO -- : Rendered api/users/create.js
on.jbuilder (3.2ms)
I, [2015-03-17T05:15:27.701395 #28450] INFO -- : Completed 200 OK in 223ms (Vie
ws: 6.3ms | ActiveRecord: 10.0ms)
the server should response a json in the format:
{"user":{"id":3,"email":"carlos#prueba.com","auth_token":"dc45800fddee07cf9b300d2765283cb2"}}
Most tutorials are outdated and try to use the apache library however I did find a working one.
While trying to manipulate a Team Treehouse Tutorial ( https://teamtreehouse.com/library/build-a-weather-app/ ) to work for an event finder api instead of their weather api, I ran into the same problem.
They use the OkHttp library
compile the OkHttp library into your build.gradle file under Module:app
compile 'com.squareup.okhttp:okhttp:2.4.0'
this is the most recent version as of 7/9/15
visit the api url to see if you are indeed retrieving the data and that it is in the correct format. For me I was using Eventful.com and finding events in my area.
( https://api.eventful.com/json/events/search?l=arizona&within=15&units=miles&app_key= ) where my app key would go after the "=" at the end of the url.
at this point everything was working great, now I needed to add the OkHttp code to download the json data
add internet permissions to your manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thestephenmiller.myApp" >
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Open the class or activity where the request will be made and add the following code.
String eventfulUrl = "https://api.eventful.com/json/events/search?l=arizona&within=15&units=miles&app_key="+apiKey;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(eventfulUrl)
.build();
and make the call
`
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
}
#Override
public void onResponse(Response response) throws IOException {
try {
if (response.isSuccessful()) {
Log.v(TAG, response.body().string());
}
} catch (IOException e) {
Log.e(TAG, "Exception Caught: ", e);
}
}
});
all of which was added to onCreate()
this line
Log.v(TAG, response.body().string());
is what outputs the response to the log and is in the if statement where you can deal with the data.
The code will not get the response if the url does not start with "http://" or "https://" however the app will still run error free
I'm trying to implement a pusher service in my Android app, doesn't have access to the server just copying from an iOS app previous implementation. Everything works fine in connection process but when subscribe to a private channel the authentication fails with:
"com.pusher.client.AuthorizationFailureException: java.io.FileNotFoundException: https://authorization_url"
The implementation goes like this:
HttpAuthorizer authorizer = new HttpAuthorizer(PUSHER_AUTH_URL);
PusherOptions options = new PusherOptions().setEncrypted(true).setWssPort(443).setAuthorizer(authorizer);
pusher = new Pusher(PUSHER_KEY, options);
pusher.connect(new com.pusher.client.connection.ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
if (change.getCurrentState() == ConnectionState.CONNECTED) {
Channel channel = pusher.subscribePrivate(PUSH_CHANNEL, new PrivateChannelEventListener() {
#Override
public void onAuthenticationFailure(String s, Exception e) {
Log.w("PUSHER", "Channel subscription authorization failed");
}
#Override
public void onSubscriptionSucceeded(String s) {
Log.w("PUSHER", "Channel subscription authorization succeeded");
}
#Override
public void onEvent(String s, String s2, String s3) {
Log.w("PUSHER", "An event with name " + s2 + " was delivered!!");
}
}, "my-event");
}
}
#Override
public void onError(String message, String code, Exception e) {
Log.w("PUSHER", "There was a problem connecting with code " + code + " and message " + message);
}
}, ConnectionState.ALL);
UPDATE
I'm sure that the problem is with the authentication, there is a function call in iOS version that set some headers to the channel subscription or something like that:
(void)pusher:(PTPusher *)pusher willAuthorizeChannel:(PTPusherChannel *)channel withRequest:(NSMutableURLRequest *)request;
{
[request addAuthorizationHeadersForUser:self.credentials.user];
}
Im trying to figure out where to add the headers in android, try to add it to the authorizer but nothing change:
authorizer.setHeaders(addMapAuthorizationHeaders());
Any idea of what is the equivalent in Android of that iOS function: willAuthorizeChannel??
Ok solved, it was what I thought, the HttpAuthorizer needed a set of headers that you can set directly when creating it like:
HttpAuthorizer authorizer = new HttpAuthorizer(PUSHER_AUTH_URL);
authorizer.setHeaders(MY_AUTH_HEADERS); //a HashMap with the headers
PusherOptions options = new PusherOptions().setEncrypted(true).setWssPort(443).setAuthorizer(authorizer);
pusher = new Pusher(PUSHER_KEY, options);
And with that works fine, in case somebody have a similar problem.
EDIT:
this is how to set the authorization headers. It's a Map set to "Key" "Value" pair for example:
public static HashMap<String, String> getMapAuthorizationHeaders() {
try {
HashMap<String, String> authHeader = new HashMap<>();
authHeader.put("HeaderKey1", "HeaderValue1");
authHeader.put("HeaderKey2", "HeaderValue2");
return authHeader;
} catch (Exception e) {
return null;
}
}
So the pusher config will be like:
authorizer.setHeaders(getMapAuthorizationHeaders());
I've been struggling with this as well... the solution is simple.
First check this out: https://github.com/pusher/pusher-websocket-java/blob/master/src/main/java/com/pusher/client/util/HttpAuthorizer.java
Then implement the abstract interface Authorizer and override the authorize method with your own code and that's it, you get the same thing as on the iOS.
Some snippet to get you started (with a custom constructor):
CustomSocketHttpAuthorizer authorizer = new CustomSocketHttpAuthorizer(ServerComm.API_MAIN_LINK + ServerComm.API_LINK_PUSHER_AUTH, pusherServerAuthTimeStamp, MessageActivity.this);
PusherOptions options = new PusherOptions().setAuthorizer(authorizer).setEncrypted(true);;
clientPusher = new Pusher(ServerComm.PUSHER_CLIENT_KEY, options);
clientPusher.connect(new ConnectionEventListener() .....