The FCM Token ID has been generated and I want it to send to the PHP server and then store it in a variable. What should be the approach?
#Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
}
PHP Code
<?php
$token = $_POST["tokenid"];
echo ($token);
?>
You can store you FCM-Id in Preference and then pass this FCM-Id to backend pass it as a parametr using API calling. here below i'm get FCM-Id and pas to PHP using API.
MyFirebaseInstanceIDService.java
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
private static final String TAG = "MyFirebaseIIDService";
Context context;
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. Note that this is called when the InstanceID token
* is initially generated so this is where you would retrieve the token.
*/
// [START refresh_token]
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
context = getApplicationContext();
AppPreference.setStringPref(context, AppPreference.PREF_SIGNUP_FCM_ID, AppPreference.PREF_KEY.PREF_KEY_FCM_ID,
refreshedToken);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
// [END refresh_token]
/**
* Persist token to third-party servers.
* <p>
* Modify this method to associate the user's FCM InstanceID token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
Map<String, String> params = new HashMap<String, String>();
String device_id = Common.getDeviceId(this);
params.put(FCM_TOKEN, token);
params.put(DEVICEID, device_id);
params.put(DEVICE_TYPE, device_type);
JsonObjectRequest request = new JsonObjectRequest(FCM_TOKEN_URL, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
parseJsonPersonalDetail(response);
} catch (Exception e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (error.networkResponse != null) {
int statusCode = error.networkResponse.statusCode;
NetworkResponse response = error.networkResponse;
Log.d("testerror", "" + statusCode + " " + response.data);
}
}
}) {
#Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<String, String>();
headers.put("User-agent", "Mozilla/5.0 (TV; rv:44.0) Gecko/44.0 Firefox/44.0");
return headers;
}
};
Common.setVolleyConnectionTimeout(request);
ApplicationClass.getInstance().getRequestQueue().add(request);
}
/**
* <b>Description</b> - Get back response for calling callUserDetailSave API
*
* #param jsonObject - Pass API response
*/
private void parseJsonPersonalDetail(JSONObject jsonObject) {
try {
Log.i("get response", "get response" + jsonObject);
if (jsonObject.toString().contains(Constant.JSON_KEY.MSG)) {
String message = jsonObject.getString(Constant.JSON_KEY.MSG);
String status = jsonObject.getString(Constant.JSON_KEY.CODE);
}
} catch (Exception e) {
e.getStackTrace();
}
}
}
Here first i'm get FCM id then call API method sendRegistrationToServer and pass token in API as a paramter so back-end developer get this token from API parameter.
Here i'm pass three parameters
params.put(FCM_TOKEN, token);
params.put(DEVICEID, device_id);
params.put(DEVICE_TYPE, device_type);
device_id and device_type pass because it's my requirment.
Add dependency in app level gradle file for calling Volley API call :
implementation 'com.android.volley:volley:1.1.0'
Checkout i'm created Demo for you: Demo
Volley Libraries Example :
Tutorial 1
Tutorial 2
Tutorial 3
Related
So I have this POST request made to the server and based on an argument the server will return error message within the errorBody() of Retrofit. I am trying to handle that Plain Text error returned by the server and then display it to the user within my Android application which uses Java. Below is my current attempt but this is giving me this error in Logcat:
#Url cannot be used with #POST URL (parameter #1)
Here is 400 response from the server:
Interface:
public interface ChangePickLocationClient
{
#GET
Call<ResponseBody> checkItem(#Url String url, #Header("Authorization") String authToken);
#GET
Call<String> getStringError(#Url String url, #Header("Authorization") String authToken);
#POST("Pick/ChangePickLocationAcceptChange")
Call<String> changePickLocationPOST(#Url String url, #Header("Authorization") String authToken, #Body
ChangePickLocationPostModel changePickLocationPostModel);
}
Implementation:
private static final String BASE_URL = "http://00.00.00.1234/api/";
Gson mGson = new Gson();
Retrofit retrofit = new Retrofit.Builder().client(new OkHttpClient())
.baseUrl(BASE_URL).addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(mGson))
.build();
ChangePickLocationClient ChangePickLocationClient =
retrofitPOST.create(ChangePickLocationClient.class);
String itemNumber = itemNumberValue.getText().toString();
newPickLocationValue.setText(newPickLocationValue.getText().toString().toUpperCase());
String newPickLocation = newPickLocationValue.getText().toString();
String token = globalClass.getActiveToken();
final ChangePickLocationClient mChangePickLocationInterface =
retrofit.create(ChangePickLocationClient.class);
Call<String> mCallErrorPOST = mChangePickLocationInterface.changePickLocationPOST
(postUrl, "Bearer " + globalClass.getActiveToken(),
changePickLocationPostModel);
call.enqueue(new Callback<ChangePickLocationPostModel>()
{
#Override
public void onResponse(Call<ChangePickLocationPostModel> call,
Response<ChangePickLocationPostModel> response)
{
String mPlainTextResponse = null;
try {
if(response.errorBody() != null)
{
mPlainTextResponse = response.errorBody().string();
}
} catch (IOException e)
{
e.printStackTrace();
}
Toast.makeText(ChangePickLocation.this, mPlainTextResponse
,Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ChangePickLocationPostModel> call, Throwable t)
{
Toast.makeText(ChangePickLocation.this, "Unknown server error!"
,Toast.LENGTH_SHORT).show();
}
});
When the response is 400, the second call being made needs to be a clone() call. This is because the Call cannot be used more than once as stated in the documentation.
use this:
call.clone().enqueue(new Callback<ChangePickLocationPostModel>()
instead of
call.enqueue(new Callback<ChangePickLocationPostModel>()
I just need to send a push notification to a specific users inside my Button OnClickListener. Is it possible with userId and all information of this specific user?
this is my Button OnClickListener() code
richiedi_invito.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
lista_richieste = (ArrayList) dataSnapshot.child("classi").child(nome).child("lista_richieste").getValue();
verifica_richieste = (String) dataSnapshot.child("classi").child(nome).child("richieste").getValue();
if (!lista_richieste.contains(userID)){
ArrayList lista_invito = new ArrayList();
lista_invito.add(userID);
if (verifica_richieste.equals("null")){
databaseReference.child("classi").child(nome).child("richieste").setValue("not_null");
databaseReference.child("classi").child(nome).child("lista_richieste").setValue(lista_invito);
}
else{
lista_richieste.add(userID);
databaseReference.child("classi").child(nome).child("lista_richieste").setValue(lista_richieste);
}
//invitation code here
Fragment frag_crea_unisciti = new CreaUniscitiFrag();
FragmentManager fragmentManager= getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, frag_crea_unisciti);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Toast.makeText(getActivity(), "Richiesta di entrare inviata correttamente", Toast.LENGTH_SHORT).show();
}else{
Snackbar.make(layout,"Hai giĆ richiesto di entrare in questa classe",Snackbar.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
});
To send a push notification to a specific single user with Firebase, you only need is FCM registration token which is the unique identifier of the user device to receive the notification.
Here is Firebase FCM documentation to get this token : FCM Token registration
Basically :
You get a FCM token for the user
Then you store this FCM token on your server or database by associating this FCM token with the user ID for example.
When you need to send a notification, you can retrieve this FCM token stored on your server or database with the user id and use Firebase Cloud Functions. Here is a specific case study to send a notification for a specific user : Cloud Functions
Only the user id itself isn't enough to send a notification for a specific user.
First, the user has to generate
String token = FirebaseInstanceId.getInstance().getToken();
and then store it in Firebase database with userId as key or you can subscribe the user to any topic by FirebaseMessaging.getInstance().subscribeToTopic("topic");
To send the notification you have to hit this API: https://fcm.googleapis.com/fcm/send
With headers "Authorization" your FCM key and Content-Type as "application/json" the request body should be:
{
"to": "/topics or FCM id",
"priority": "high",
"notification": {
"title": "Your Title",
"text": "Your Text"
},
"data": {
"customId": "02",
"badge": 1,
"sound": "",
"alert": "Alert"
}
}
Or you can use okHttp which is not recommended method because your FCM key will be exposed and can be misused.
public class FcmNotifier {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
public static void sendNotification(final String body, final String title) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
OkHttpClient client = new OkHttpClient();
JSONObject json = new JSONObject();
JSONObject notifJson = new JSONObject();
JSONObject dataJson = new JSONObject();
notifJson.put("text", body);
notifJson.put("title", title);
notifJson.put("priority", "high");
dataJson.put("customId", "02");
dataJson.put("badge", 1);
dataJson.put("alert", "Alert");
json.put("notification", notifJson);
json.put("data", dataJson);
json.put("to", "/topics/topic");
RequestBody body = RequestBody.create(JSON, json.toString());
Request request = new Request.Builder()
.header("Authorization", "key=your FCM key")
.url("https://fcm.googleapis.com/fcm/send")
.post(body)
.build();
Response response = client.newCall(request).execute();
String finalResponse = response.body().string();
Log.i("kunwar", finalResponse);
} catch (Exception e) {
Log.i("kunwar",e.getMessage());
}
return null;
}
}.execute();
}
}
NOTE: THIS SOLUTION IS NOT RECOMMENDED BECAUSE IT EXPOSES FIREBASE API KEY TO THE PUBLIC
Another way is make a user subscribe to a topic named after his/her uid. then send the notification to a topic with the uid name.
I haven't tested this myself yet but I have read it here sometime ago.
I have written a basic app using Java, Google Web Toolkit and Google Cloud Datastore. For authentication I am using Firebase. When the front end makes a RPC call it passes the user token so that the backend can validate it.
I would like to create a VerifyToken class in the backend, which will receive a user token, call the Firebase verifyIdToken to verify it, then return the user uid or 0 if the user token has not been successfully verified. The class which receives the RPC call will then use the uid to get data and return it in the RPC response.
Here's the current code:
public class VerifyToken
{
public String verify(String token)
{
String uid = "0";
try
{
//Connect to Firebase
FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(new FileInputStream("firebaseJsonHere"))
.setDatabaseUrl("dbUrlHere")
.build();
FirebaseApp.initializeApp(options);
//Verify the token
FirebaseAuth.getInstance().verifyIdToken(token)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
System.out.println("uid decoded = " + uid);
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e)
{
System.out.println(e.getMessage());
}
});
}catch(Exception e){
System.out.println("Exception: " + e.getMessage());
}
//Return the uid or 0 if not validated
return uid;
}
}
Please could someone let me know how to get the result from the SuccessListener. I can see that the uid is successfully decoded, just not sure how to get the result back.
Many thanks,
Ed
I guess you can do:
public String verify(String token)
{
String uid = "0";
try
{
//Connect to Firebase
FirebaseOptions options = new FirebaseOptions.Builder()
.setServiceAccount(new FileInputStream("firebaseJsonHere"))
.setDatabaseUrl("dbUrlHere")
.build();
FirebaseApp.initializeApp(options);
//Verify the token
FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(token).getResult();
uid = decodedToken.getUid();
}catch(Exception e){
System.out.println("Exception: " + e.getMessage());
}
//Return the uid or 0 if not validated
return uid;
}
I am not a huge fan of String uid = "0"; though, setting it to null instead sounds better to me.
I'm writing an android application which uses rest services for user regitration and more but running into trouble with my login service. for some reason the requestparams i put into my service call on android side are not being found within my rest service.
could anny 1 tell me what i'm doing wrong or link to a guide which explains how to solve this problem?
Relevant android functions:
public void loginUser(View view) {
// Get username and password values
String username = usernameEdit.getText().toString();
String password = passwordEdit.getText().toString();
// Instantiate Http Request Param Object
RequestParams params = new RequestParams();
// Check if username & password is not null
if(Utility.isNotNull(username) && Utility.isNotNull(password)) {
// Http parameters
params.put("username", username);
params.put("password", password);
invokeWS(params);
} else {
Toast.makeText(getApplicationContext(), "Vul een gebruikersnaam en of " +
"wachtwoord in", Toast.LENGTH_LONG).show();
}
}
// Method that performs RESTful webservice invocations
public void invokeWS(RequestParams params) {
// Make RESTful webservice call using AsyncHttpClient object
AsyncHttpClient client = new AsyncHttpClient();
client.post("http://10.0.2.2:8080/NTR_application/rest/session", params, new AsyncHttpResponseHandler() {
// When the response returned by REST has Http response code '200'
#Override
public void onSuccess(String response) {
Toast.makeText(getApplicationContext(), "You are successfully logged in!" + response, Toast.LENGTH_LONG).show();
// Gets an JSON object with user Data
// Write user Data to SQLite
User user = new Gson().fromJson(response, User.class);
db.addUser(user);
// Navigate to Home screen
navigatetoHomeActivity();
}
// When the response returned by REST has Http response code other than '200'
#Override
public void onFailure(int statusCode, Throwable error,
String content) {
Toast.makeText(getApplicationContext(), "ERROR!" + content + error + statusCode, Toast.LENGTH_LONG).show();
}
});
}
and the rest services which is called :
#Path("/session")
public class UserService {
private Controller controller = new Controller();
#POST //Post so you can't see the information in the browser history easily
#Produces(MediaType.APPLICATION_JSON)
public Response authenticate(#QueryParam("username") String username, #QueryParam("password") String password){
User user = null;
try {
user = controller.authenticate(username, password);
} catch (NoSuchAlgorithmException | SQLException e) {
System.out.println("Authentication caught an exception; failed for: " + username);
e.printStackTrace();
}
if (user != null){
String json = new Gson().toJson(user);
return Response.status(200).entity(json).build();
} else {
return Response.status(401).entity("Username and/or password is incorrect").build();
}
}
}
Mistake was obvious once i saw it, since i use a #POST i need to use #FormParam instead of #QueryParam.
tutorial i used to write these methods used #GET to login which is insecure.
I am trying to write a server side Facebook Notification service in my GWT app. The idea is that I will run this as a timertask or cron job sort of.
With the code below, I get a login URL, I want to be able to Login programmatically as this is intended to be automated (Headless sort of way). I was gonna try do a submit with HTMLunit but I thought the FB API should cater for this.
Please advice.
public class NotificationServiceImpl extends RemoteServiceServlet implements NotificationService {
/**serialVersionUID*/
private static final long serialVersionUID = 6893572879522128833L;
private static final String FACEBOOK_USER_CLIENT = "facebook.user.client";
long facebookUserID;
public String sendMessage(Notification notification) throws IOException {
String api_key = notification.getApi_key();
String secret = notification.getSecret_key();
try {
// MDC.put(ipAddress, req.getRemoteAddr());
HttpServletRequest request = getThreadLocalRequest();
HttpServletResponse response = getThreadLocalResponse();
HttpSession session = getThreadLocalRequest().getSession(true);
// session.setAttribute("api_key", api_key);
IFacebookRestClient<Document> userClient = getUserClient(session);
if(userClient == null) {
System.out.println("User session doesn't have a Facebook API client setup yet. Creating one and storing it in the user's session.");
userClient = new FacebookXmlRestClient(api_key, secret);
session.setAttribute(FACEBOOK_USER_CLIENT, userClient);
}
System.out.println("Creating a FacebookWebappHelper, which copies fb_ request param data into the userClient");
FacebookWebappHelper<Document> facebook = new FacebookWebappHelper<Document>(request, response, api_key, secret, userClient);
String nextPage = request.getRequestURI();
nextPage = nextPage.substring(nextPage.indexOf("/", 1) + 1); //cut out the first /, the context path and the 2nd /
System.out.println(nextPage);
boolean redirectOccurred = facebook.requireLogin(nextPage);
if(redirectOccurred) {
return null;
}
redirectOccurred = facebook.requireFrame(nextPage);
if(redirectOccurred) {
return null;
}
try {
facebookUserID = userClient.users_getLoggedInUser();
if (userClient.users_hasAppPermission(Permission.STATUS_UPDATE)) {
userClient.users_setStatus("Im testing Facebook With Java! This status is written using my Java code! Can you see it? Cool :D", false);
}
} catch(FacebookException ex) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while fetching user's facebook ID");
System.out.println("Error while getting cached (supplied by request params) value " +
"of the user's facebook ID or while fetching it from the Facebook service " +
"if the cached value was not present for some reason. Cached value = {}" + userClient.getCacheUserId());
return null;
}
// MDC.put(facebookUserId, String.valueOf(facebookUserID));
// chain.doFilter(request, response);
} finally {
// MDC.remove(ipAddress);
// MDC.remove(facebookUserId);
}
return String.valueOf(facebookUserID);
}
public static FacebookXmlRestClient getUserClient(HttpSession session) {
return (FacebookXmlRestClient)session.getAttribute(FACEBOOK_USER_CLIENT);
}
}
Error message:
[ERROR] com.google.gwt.user.client.rpc.InvocationException: <script type="text/javascript">
[ERROR] top.location.href = "http://www.facebook.com/login.php?v=1.0&api_key=MY_KEY&next=notification";
[ERROR] </script>