We were using GoogleCloudMessaging.getInstance(context).send(context.getString(R.string.gcm_defaultSenderId) + "#gcm.googleapis.com", mId, mBundle); to send upstream messages, but since I was trying to migrate new fcm concept, I need to change that too, but could not find any documentation yet.
My best guess is to use :
RemoteMessage message = new RemoteMessage.Builder(<?>).setMessageId(mId).setData ...
FirebaseMessaging.getInstance().send(message);
but then what is it the Builder takes as a parameter? Yet again, could not find api...
So simply as title states, how to send upstream messages using new fcm concept?
Well, my answer comes fast. Keeping question and answer for future reference. I have found the answer on https://firebase.google.com/docs/cloud-messaging/android/upstream#sample-send
thanks to google's smart exclusion to search results In order to show you the most relevant results, we have omitted some entries very similar to the 2 already displayed.
If you like, you can repeat the search with the omitted results included.
new API would be like:
FirebaseMessaging fm = FirebaseMessaging.getInstance();
fm.send(new RemoteMessage.Builder(SENDER_ID + "#gcm.googleapis.com")
.setMessageId(Integer.toString(msgId.incrementAndGet()))
.addData("my_message", "Hello World")
.addData("my_action","SAY_HELLO")
.build());
Well you can send your message directly to android devices from android application, here is the simple implementation I have done and it works great for me.
compile android volley library
compile 'com.android.volley:volley:1.0.0'
Just copy paste this simple function ;) and your life will become smooth just like knife in butter. :D
public static void sendPushToSingleInstance(final Context activity, final HashMap dataValue /*your data from the activity*/, final String instanceIdToken /*firebase instance token you will find in documentation that how to get this*/ ) {
final String url = "https://fcm.googleapis.com/fcm/send";
StringRequest myReq = new StringRequest(Request.Method.POST,url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(activity, "Bingo Success", Toast.LENGTH_SHORT).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(activity, "Oops error", Toast.LENGTH_SHORT).show();
}
}) {
#Override
public byte[] getBody() throws com.android.volley.AuthFailureError {
Map<String,String> rawParameters = new Hashtable<String, String>();
rawParameters.put("data", new JSONObject(dataValue).toString());
rawParameters.put("to", instanceIdToken);
return new JSONObject(rawParameters).toString().getBytes();
};
public String getBodyContentType()
{
return "application/json; charset=utf-8";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "key="+YOUR_LEGACY_SERVER_KEY_FROM_FIREBASE_CONSOLE);
return headers;
}
};
Volley.newRequestQueue(activity).add(myReq);
}
Note
If you want to send message to topics so you can change parameter instanceIdToken to something like /topics/topicName.
For groups implementation is the same but you just need to take care of parameters. checkout Firebase documentation and you can pass those parameters.
let me know if you face any issue.
Related
I need a working example for a custom API for Microsoft Azure App Service.
I could not get any useful or working information/examples for that, or they just show each time different approaches which are outdated?!?!
For now I have a working table controller which gets information from database and returns it back to my Android client. Now I need to define a custom API Controller to get a string back. In the examples they are all sending an object to the service in order to get an object back. I do not want to send anything to the API, just retrieve some information back from a GET Request.
Regards
// EDIT - Added / edited client / server code to Post a String.
You can use the following code to do a GET request on the auto generated API controller Visual Studio creates (ValuesController).
private void getStringFromAzure() throws MalformedURLException {
// Create the MobileService Client object and set your backend URL
String yourURL = "https://yourApp.azurewebsites.net/";
MobileServiceClient mClient = new MobileServiceClient(yourURL, this);
// Your query pointing to yourURL/api/values
ListenableFuture<JsonElement> query = mClient.invokeApi("values", null, GetMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
// Since you are on a async task, you need to show the result on the UI thread
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(Throwable throwable) {
Log.d(TAG, "onFailure: " + throwable.getMessage());
}
});
}
public void sendString(final String someString) throws MalformedURLException {
// Your query pointing to /api/values/{String}
ListenableFuture<JsonElement> query = mClient.invokeApi("values/" + someString, null, PostMethod, null);
// Callback method
Futures.addCallback(query, new FutureCallback<JsonElement>() {
#Override
public void onSuccess(JsonElement jsonElement) {
// You are expecting a String you can just output the result.
final String result = jsonElement.toString();
}
#Override
public void onFailure(Throwable throwable) { }
});
}
The backend API: (ValuesController)
{
// Use the MobileAppController attribute for each ApiController you want to use
// from your mobile clients
[MobileAppController]
public class ValuesController : ApiController
{
// GET api/values
public string Get()
{
return "Hello World!";
}
// POST api/values/inputString
public string Post(string inputString)
{
return inputString;
}
}
}
You can also send parameters along in the following way:
List<Pair<String, String>> parameters = new ArrayList<>();
parameters.add(new Pair<>("name", "John"));
parameters.add(new Pair<>("password", "fourwordsalluppercase"));
ListenableFuture<JsonElement> query = client.invokeApi("yourAPI", PostMethod, parameters);
Or as json in the body:
JsonObject body = new JsonObject();
body.addProperty("currentPassword", currentPassword);
body.addProperty("password", password);
body.addProperty("confirmPassword", confirmPassword);
ListenableFuture<JsonElement> query = mClient.invokeApi("yourAPI", body, PostMethod, null);
Based on my understanding, I think there are two parts in your question which include as below. And I think you can separately refer to two sections to get the answers and write your own example.
How to define a custom API on Azure Mobile App to retrieve data from database? Please refer to the section Custom APIs to know how to do with Azure Mobile App backend.
How to call a custom API from Android App? Please refer to the section How to: Call a custom API to know how to do with Android SDK.
I need to connect to a socket and send credential info in order to start receiving upcoming data over RECEIVE_CRISIS.
I'm using the library Socket.IO for Android code. It's really hard to debug since I got no Log from the connection, I don't know why and where it fails. I just never received anything from the server since I started working on the Android side. Is the NSDictionary equivalent to the JSONObject on Android? Is sendEvent equivalent to send() or emit() on Android? Do I need to send the JSON as an Object or an Array? Finally, how to I get the log error?
It's working on iOS part so I'm kinda lost..
This is the iOS code : (I modify the address for safe purpose):
NSDictionary *params=#{#"user":_username,#"orgid":_organizationId};
[_socketIO connectToHost:#"nodejs.myserver.com" onPort:3000 ];
[_socketIO sendEvent:#"joinparty" withData:params];
This is the Android code :
private void connectAndListen(int username) throws Exception {
socket = IO.socket("nodejs.myserver.com:3000");
socket.connect();
JSONObject json = new JSONObject();
json.put("user", username);
json.put("orgid", settings.getString("orgid", ""));
Log.e(TAG, json.toString());
socket.send("joinparty",json);
socket.emit("joinparty", json);
socket.on(RECEIVE_CRISIS, onCrisis);
}
UPDATED QUESTION
private void connectAndListen(int id) throws Exception {
IO.setDefaultSSLContext(SSLContext.getDefault());
// Set default hostname
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return true;
}
};
IO.setDefaultHostnameVerifier(hostnameVerifier);
IO.Options options = new IO.Options();
// set as an option
options.sslContext = SSLContext.getDefault();
options.hostnameVerifier = hostnameVerifier;
options.secure = true;
socket = IO.socket("nodejs.myserver.com:3000", options);
socket.connect();
JSONObject json = new JSONObject();
json.put("user", id);
json.put("orgid", settings.getString("orgid", ""));
Map<Object, Object> arrays = new HashMap<>();
arrays.put("user", id);
arrays.put("orgid",settings.getString("orgid", "") );
socket.emit("joinparty", arrays);
socket.on(RECEIVE_CRISIS, onCallback);
socket.on("connect_error", onCallback);
socket.on("connect", onCallback);
socket.on("Object", onCallback);
socket.on("connect_timeout", onCallback);
}
private Emitter.Listener onCallback = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.e(TAG, args[0]+"");
}
};
Is the NSDictionary is equivalent to the JSONObject on Android?
No, it's not. NSDictionary is a class cluster, meaning that the actual implementation is hidden from you, the API user. In fact, the Foundation framework will choose the appropriate implementation at run time based on amount of data etc. The closest to it for Java is Map<Object, Object>
Is sendEvent equivalent to send() or emit() on Android?
It is emit for Android. from official documentation
DO I need to send the JSON as an Object or an Array?
Try sending a Map instead. JSON is a different thing. If your server is expecting data in JSON format, than only send it.
Finally, How to I get the log error?
You need to use combination of emitter and manager for it.
This Android app is using Android Studio. The function is to scan and display data from the beacon/eddystone. The app already functions and after the scanning stops, the data saves to the local file. But my problem is when I have to transfer the scanning data to the server, I have to ent it to the back-end server. But I really didn't know what is the best way as I'm a beginner.
Here is the code that the data will transfer to the local data:
private void stopScanning(Button scanButton) {
try {
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
// TODO - OK, what now then?
}
String scanData = logString.toString();
if (scanData.length() > 0)
{
// Write file
fileHelper.createFile(scanData);
// Display file created message.
Toast.makeText(getBaseContext(),
"File saved to:" + getFilesDir().getAbsolutePath(),
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
} else {
// We didn't get any data, so there's no point writing an empty file.
Toast.makeText(getBaseContext(),
"No data captured during scan, output file will not be created.",
Toast.LENGTH_SHORT).show();
scanButton.setText(MODE_STOPPED);
}
}
To send Data to a server there are many ways, BUT I PREFER you use Volley Library because it's faster and easier
You can use volley for fetching and sending data ,For example:
//Request serever for JsonObject
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//Your code to proceed with fetched data
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
//This is the method used to put params into the body, this what you will have to use for sending post data
#Override
public Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
params.put("name","jois");
return params;
}
};
Volley.newRequestQueue(getApplicationContext()).add(request);
compile 'com.mcxiaoke.volley:library:1.0.19' This is the dependice you will have to add in build.gradle file to use volley library
I hope this was helpful, ThankYou
I am parsing a json response using gson. However in my case I am getting different response for success and failure.
So I am unable to parse the data, because in my utility class I have created some serilized field those are not present for both the scenario.
e.g. when registration is success I am using user key to get the user details while when registration is failed I am using error field to get error message.
I have knowledge about json parsing and in that we we do parsing step by step like if success is true then parse for user details otherwise parse for error. Again in json parsing we have method has which check a key is exist or not. And I am looking for something similar in gson also.
Below is my code snippet please check it
Get Register Data from Server
private void getRegisterData(String email, String password, String full_name,String phone) {
WdApplication= (WAdvantageApplication) this.getApplication();
RequestQueue queue = application.getRequestQueue();
HashMap<String, String> headerMap = new HashMap<String, String>();
headerMap.put(RequestHeaders.CONTENT_TYPE, RequestHeaders.CONTENT_TYPE_JSON);
HashMap<String, String> dataMap = new HashMap<String, String>();
dataMap.put("email", email);
dataMap.put("password", password);
dataMap.put("phone", phone);
dataMap.put("fullname", full_name);
GsonRequest<RegisterDetails> request = new GsonRequest<RegisterDetails>(GsonRequest.Method.POST, URLConstant.REGISTER_URL, RegisterDetails.class, headerMap, dataMap, successListener, failureListener);
queue.add(request);
}
private Response.Listener successListener = new Response.Listener<RegisterDetails>() {
#Override
public void onResponse(RegisterDetails registerDetails) {
Log.e("success", "Success");
finish();
}
};
private Response.ErrorListener failureListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Log.e("fail", "Registration failed");
}
};
my RegisterDetails class
#SerializedName("user")
private UserDetails userDetails;
#SerializedName("success")
private String success;
#SerializedName("error")
Information info;
So for success is true I want only user part and for success is false I want error part.
If I am doing anything wrong please rectify me , Thanks
I am not sure what you are asking about, but in gson if you are getting success key and user key (if it's success) and error (if something goes wrong)in single response, you can code something like this.
if(registerDetails.getSuccess().equalsIgnoreCase("true"))
{
// use registerDetails.getUserDetails();
}
else
{
// use registerDetails.getInfo();
}
Not sure about GSON but if you use Jackson, you can provide an annotation like this
#JsonIgnoreProperties(ignoreUnknown = true)
and then you can use the same model class for success or failure, if it is a success, the userDetails will be set, if it is a failure, the error part will be set.
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() .....