GCM Notification Receiver/Token Registration - java

EDIT: Figured it out -- see answer below
I'm attempting to generate registration tokens, store them in a server, and then use the tokens to send push notifications. At this point, I've successfully sent and stored registration tokens and am sending notifications from a web API, but they aren't arriving to my device. I was wondering if/what I should replace R.string.gcm_defaultSenderId with (i.e. the sender key from GCM?) I'm including my code for token registration as well as my notification listener below.
public class GCMRegistrationIntentService extends IntentService {
//Constants for success and errors
public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
public static final String REGISTRATION_ERROR = "RegistrationError";
private Context context;
private String sessionGUID = "";
private String userGUID = "";
//Class constructor
public GCMRegistrationIntentService() {
super("");
}
#Override
protected void onHandleIntent(Intent intent) {
context = getApplicationContext();
sessionGUID = RequestQueueSingleton.getInstance(context).getSessionGUID();
userGUID = RequestQueueSingleton.getInstance(context).getUserGUID();
//Registering gcm to the device
registerGCM();
}
//Registers the device to Google Cloud messaging and calls makeAPICall to send the registration
//token to the server
private void registerGCM() {
//Registration complete intent initially null
Intent registrationComplete;
//declare a token, try to find it with a successful registration
String token;
try {
//Creating an instanceid
InstanceID instanceID = InstanceID.getInstance(this);
//Getting the token from the instance id
token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
//Display the token, need to send to server
Log.w("GCMRegIntentService", "token:" + token);
String android_id = Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);
int osTypeCode = Constants.OST_ANDROID;
JSONObject parms = new JSONObject();
try {
parms.put("deviceID", android_id);
parms.put("OSTypeCode", osTypeCode);
parms.put("token", token);
} catch (JSONException e) {
e.printStackTrace();
}
Transporter oTransporter = new Transporter(Constants.TransporterSubjectUSER,
Constants.REGISTER_NOTIFICATION_TOKEN, "", parms, userGUID, sessionGUID);
oTransporter.makeAPICall(getApplicationContext(), "");
//on registration complete. creating intent with success
registrationComplete = new Intent(REGISTRATION_SUCCESS);
//Putting the token to the intent
registrationComplete.putExtra("token", token);
} catch (Exception e) {
//If any error occurred
Log.w("GCMRegIntentService", "Registration error");
registrationComplete = new Intent(REGISTRATION_ERROR);
}
//Sending the broadcast that registration is completed
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
}
And the listener service:
public class GCMPushReceiverService extends GcmListenerService {
private static final String TAG = "GCMPushReceiverService";
//with every new message
#Override
public void onMessageReceived(String from, Bundle data){
System.out.println("WE'VE RECIEVED A MESSAGE");
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
sendNotification(message);
}
private void sendNotification(String message) {
Intent intent = new Intent(this, LogInPage.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = 0;
PendingIntent pendingIntent =
PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this);
noBuilder.setContentTitle("title");
noBuilder.setContentText(message);
noBuilder.setContentIntent(pendingIntent);
noBuilder.setSound(sound);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
}
}
Lastly, as it may be of some assistance, the information transporter/networking class:
public class Transporter {
private String subject;
private String request;
private String key;
private Date lastUpdateDate;
private boolean forceLoad = false;
private Date requestDate;
private Date responseDate;
private int status;
private String statusMsg = "";
private String tempKey = "";
private JSONObject additionalInfo = null;
private JSONObject parameters;
public static String sessionGUID = "";
public static String userGUID = "";
public static String SERVER = Constants.qa_api;
//transporter object to interact with the server, containing information about the request
//made by the user
public Transporter(String pSubject, String pRequest, String pKey,
JSONObject parms, String userGUID, String sessionGUID)
{
subject = pSubject;
request = pRequest;
key = pKey;
parameters = parms;
setUserGUID(userGUID);
setSessionGUID(sessionGUID);
}
//implements an API call for a given transporter, takes 2 arguments:
//the application context (call getApplicationContext() whenever it's called)
//and a String that represents the field that we are trying to update (if there is one)
//i.e. if we are calling getUserFromSession(), we want the user guid so jsonID = "userGUID"
public void makeAPICall(final Context context, final String jsonID) {
RequestQueue mRequestQueue =
RequestQueueSingleton.getInstance(context).getRequestQueue();
String targetURL = getServerURL() + "/Transporter.aspx";
StringRequest postRequest = new StringRequest(Request.Method.POST, targetURL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String parseXML= parseXML(response);
System.out.println("response: " + parseXML);
JSONObject lastResponseContent = null;
try {
lastResponseContent = new JSONObject(parseXML);
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (lastResponseContent != null && !jsonID.equals("")) {
String info = lastResponseContent.getString(jsonID);
if (jsonID.equals("userGUID")) {
userGUID = info;
RequestQueueSingleton.getInstance(context).setUserGUID(userGUID);
}
}
//put other things in here to pull whatever info
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}) {
#Override
public byte[] getBody() throws AuthFailureError {
String body = getXML(subject,
request, "",
sessionGUID, userGUID, null, parameters);
return body.getBytes();
}
};
postRequest.setTag("POST");
mRequestQueue.add(postRequest);
}

you need to send a post to the url "https://android.googleapis.com/gcm/send":
private void sendGCM() {
StringRequest strReq = new StringRequest(Request.Method.POST,
"https://android.googleapis.com/gcm/send", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
NetworkResponse networkResponse = error.networkResponse;
Log.e(TAG, "Volley error: " + error.getMessage() + ", code: " + networkResponse);
Toast.makeText(getApplicationContext(), "Volley error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("data", "message that you send");
params.put("to", "token gcm");
Log.e(TAG, "params: " + params.toString());
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
headers.put("Authorization", "key="google key");
return headers;
}
};
}

So the Volley calls are non-sequential so the first call (to get a userGUID) didn't return before the second call (to register for notifications), so while the token registration was "successful," there was no corresponding user information so it didn't know how/where to send the push notification. To resolve, I made a special case in the makeAPICall class which created another StringRequest which first basically did the normal getUserFromSession but then recursively called MakeAPICall with the new userGUID information. To avoid an infinite loop, I used an if else statement: (if userGUID == null || userGUID.equals("")) then I did the recursive call, so when the first call returned that conditional was always false and it would only make one recursive call. This answer may be a rambling a bit, but the key take away is using onResponse to make another Volley call for sequential requests. See: Volley - serial requests instead of parallel? and Does Volley library handles all the request sequentially

Related

Sending string data to server script using volley in android fragment

Am trying to send data received from my android app to a server side php script. Am using the Volley. However, when I declare the the RequestQueue I get an error
"newRequestQueue (android.content.Context, com.android.volley.toolbox.HttpStack) cannot be applied to ()"
I tried using::
Blockquote
RequestQueue queue = Volley.newRequestQueue(this);
Blockquote
RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
Blockquote
Error is still the same on both cases. Please what am doing wrong?
PS- volley is in PostDataToEmail method of a fragment.
Here is the code below:
public void PostDataToEmail(){
final String service = service_type.toString();
final String error_message = incident.getText().toString();
final String requester = user_name.getText().toString();
final String number = mobile_no.getText().toString();
final String site = location.getText().toString();
final String support_time = timeDate.getText().toString();
final String support_date = date_field.getText().toString();
final String mode_of_contact = contact_mode.toString();
RequestQueue queue = Volley.newRequestQueue();
String url = "http://mywebsite/fromApp.php";
StringRequest postRequest = new StringRequest (Request.Method.POST, url,
new Response.Listener<String>(){
#Override
public void onResponse(String response) {
Log.d("Response", response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse (VolleyError error) {
Log.d("ERROR", "error => " +error.toString());
}
}
) {
#Override
protected Map<String, String> getParams(){
Map<String, String> params = new HashMap<String, String>();
params.put("grant_type", "password");
params.put(" ", "{{%escape/");
params.put("Service: ", service);
params.put("Error Message: ", error_message);
params.put("Requester: ", requester);
params.put("Mobile No: ", number);
params.put("Location: ", site);
params.put("Time: ", support_time);
params.put("Date: ", support_date);
params.put("Contact mode: ", mode_of_contact);
return params;
}
};
queue.add(postRequest);
}
You need to add this in your declaration. RequestQueue some=newRequestQueue(this)

How can I pass my base64 string on my web server?

Are my codes correct? I already have published this on my Web server. What happens are, it is creating a text file but the base64 string are not written on that text file.
These are my codes from Android Studio
private void uploadImage() {
final ProgressDialog loading = ProgressDialog.show(this,"Uploading...","Please wait...",false,false);
StringRequest stringRequest = new StringRequest(Request.Method.POST, UPLOAD_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
loading.dismiss();
Toast.makeText(MainActivity.this, s , Toast.LENGTH_LONG).show();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
loading.dismiss();
Toast.makeText(MainActivity.this, volleyError.getMessage().toString(), Toast.LENGTH_LONG).show();
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
String image = getStringImage(bitmap);
Map<String,String> params = new Hashtable<String, String>();
params.put("b64", image);
Log.d("base64: ", String.valueOf(params));
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
These are my codes on VS
[HttpPost]
public String ProcessImg([FromBody] string b64)
{
String base64 = b64;
String jsonStr = null;
//function to create image from b64 string
try
{
var FilePath = ConfigurationManager.AppSettings["imgFilePath"];
if (!Directory.Exists(FilePath))
{
Directory.CreateDirectory(FilePath);
}
//to create file and write base64 string
var name = DateTime.Now.ToString("MMddyyyy-HHmmss");
var FileName = Path.Combine(FilePath, name + ".png");
string path = Path.Combine(FilePath, name + ".txt");
StreamWriter file = new StreamWriter(path);
file.Write(base64);
file.Close();
if (File.Exists(FileName))
{
jsonStr = "file successfully created on server. :" + FileName;
}
else
{
jsonStr = "Sorry the file you tried to convert failed.";
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
jsonStr = ex.Message;
}
//Algo
return jsonStr;
}
StreamWriter is best used with the using keyword as it implements IDisposable which automatically calls the Dispose() method like this:
using(StreamWriter file = new StreamWriter())
{
file.Write(base64);
}
Otherwise you will have to call the Flush() method manually to write the buffered input to the disk before closing the file:
StreamWriter file = new StreamWriter();
file.Write(base64);
file.Flush();
file.Close();
The flush part is done when the stream's Dispose() method is called, thus implementing it with the using keyword automatically takes care of that.

com.android.volley.VolleyError:java.lang.NullPointerException:Attempt to invoke virtual method 'in java.lang.String.length()' on object reference [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Getting the error in Listener whenever the fb_flag is 1, m just beginner; learning volley
NullPointerException :::
Have tried to solve the error; but couldn't solve it
LoginCall.java
public class Login_Call {
Context con;
String email ="", pass = "";
String fb_flag = String.valueOf(0);
String URL = "";
UserData userData;
String Message = "Success";
Constructor for setting the data items;
public Login_Call(Context context, String email, String password, String flag) {
con = context;
this.email = email;`enter code here`
pass = password;
fb_flag = flag;
Toast.makeText(con,fb_flag, Toast.LENGTH_SHORT).show();
}
public UserData getUserDataObject() {
return userData;
}
Getting error in this method ;
Method is for mapping the string data with url;
public String getLoginAcc() {
RequestQueue queue = Volley.newRequestQueue(con);
StringRequest postRequest = new StringRequest(Method.POST, URL, new Listener<String>() {
#Override
public void onResponse(String s) {
Log.d("LoginCheck", s);
Toast.makeText(con,s, Toast.LENGTH_SHORT).show();
authenticateLoginResponse(s);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(con, "Server Not Responding" + volleyError, Toast.LENGTH_SHORT).show();
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("fb_flag", fb_flag);
params.put("email", email);
params.put("password", pass);
return params;
}
};
postRequest.setTag("Publiko Login");
postRequest.setRetryPolicy(new DefaultRetryPolicy(5000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(postRequest);
return Message;
}
private void authenticateLoginResponse(String data) {
String response;
try {
JSONObject responseObject = new JSONObject(data);
response = responseObject.getString("response");
if (response.equals("success")) {
// ToDo succes response Login Acces Granted
JSONArray responseArray = responseObject.getJSONArray("data");
JSONObject reponseInnerObject = responseArray.getJSONObject(0);
UserData user = new UserData();
user.setUsername(reponseInnerObject.getString("user_name"));
user.setEmail(reponseInnerObject.getString("email"));
user.setAddress(reponseInnerObject.getString("address"));
user.setPhone(reponseInnerObject.getString("phone"));
user.setUserid(reponseInnerObject.getString("user_id"));
userData = user;
} else {
// ToDo Failed Response Invalid Email/Password
this.Message = responseObject.getString("message");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
thanks in advance :)
Double check your URL and see if it is valid URL. In my case I missed base url.

Unable to start intent service gcm

Note:This is not a duplication or spammming since i have checked whole lot of searches.
Im currently developing an gcm integrated application and when i run on my emulator,it shows :
04-13 00:07:23.814: W/ActivityManager(366): Unable to start service
Intent { act=com.google.android.c2dm.intent.REGISTER
pkg=com.google.android.gms (has extras) } U=0: not found
My code is not similar to searches in here as I followed this tutorial https://github.com/erikswed/InstaChatX
In this tutorial,there are only 4 gcm client class,gcmbroadcast receiver,Gcm Util,Server Utilities and Constants.In those 4 classes havent mentioned about intent and in android manifest files also dont have permission:
Here is code for 4 gcm client class:
public class GcmBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GcmBroadcastReceiver";
private Context ctx;
#Override
public void onReceive(Context context, Intent intent) {
ctx = context;
PowerManager mPowerManager = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
WakeLock mWakeLock =
mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.acquire();
try {
GoogleCloudMessaging gcm =
GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
if
(GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
sendNotification("Send error", false);
} else if
(GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
sendNotification("Deleted messages on server", false);
} else {
String msg = intent.getStringExtra(DataProvider.COL_MESSAGE);
String senderEmail =
intent.getStringExtra(DataProvider.COL_SENDER_EMAIL);
String receiverEmail =
intent.getStringExtra(DataProvider.COL_RECEIVER_EMAIL);
ContentValues values = new ContentValues(2);
values.put(DataProvider.COL_TYPE,
MessageType.INCOMING.ordinal());
values.put(DataProvider.COL_MESSAGE, msg);
values.put(DataProvider.COL_SENDER_EMAIL, senderEmail);
values.put(DataProvider.COL_RECEIVER_EMAIL, receiverEmail);
context.getContentResolver().insert
(DataProvider.CONTENT_URI_MESSAGES, values);
if (Common.isNotify()) {
sendNotification("New message", true);
}
}
setResultCode(Activity.RESULT_OK);
} finally {
mWakeLock.release();
}
}
private void sendNotification(String text, boolean launchApp) {
NotificationManager mNotificationManager = (NotificationManager)
ctx.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder notification = new
NotificationCompat.Builder(ctx);
notification.setContentTitle(ctx.getString(R.string.app_name));
notification.setContentText(text);
notification.setAutoCancel(true);
notification.setSmallIcon(R.drawable.ic_launcher);
if (!TextUtils.isEmpty(Common.getRingtone())) {
notification.setSound(Uri.parse(Common.getRingtone()));
}
if (launchApp) {
Intent intent = new Intent(ctx, Chat_List.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(ctx, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
notification.setContentIntent(pi);
}
mNotificationManager.notify(1, notification.build());
}
}
This is GcmUtil class:
public class GcmUtil {
private static final String TAG = "GcmUtil";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private static final String PROPERTY_ON_SERVER_EXPIRATION_TIME = "onServerExpirationTimeMs";
/**
* Default lifespan (7 days) of a reservation until it is considered expired.
*/
public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7;
private static final int MAX_ATTEMPTS = 5;
private static final int BACKOFF_MILLI_SECONDS = 2000;
private static final Random random = new Random();
private Context ctx;
private SharedPreferences prefs;
private GoogleCloudMessaging gcm;
private AsyncTask registrationTask;
public GcmUtil(Context ApplicationContext) {
super();
ctx = ApplicationContext;
prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
String regid = getRegistrationId();
if (regid.length() == 0) {
registerBackground();
} else {
broadcastStatus(true);
}
gcm = GoogleCloudMessaging.getInstance(ctx);
}
/**
* Gets the current registration id for application on GCM service.
* <p>
* If result is empty, the registration has failed.
*
* #return registration id, or empty string if the registration is not
* complete.
*/
private String getRegistrationId() {
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.length() == 0) {
//Log.v(TAG, "Registration not found.");
return "";
}
// check if app was updated; if so, it must clear registration id to
// avoid a race condition if GCM sends a message
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion();
if (registeredVersion != currentVersion || isRegistrationExpired()) {
//Log.v(TAG, "App version changed or registration expired.");
return "";
}
return registrationId;
}
/**
* Stores the registration id, app versionCode, and expiration time in the
* application's {#code SharedPreferences}.
*
* #param regId registration id
*/
private void setRegistrationId(String regId) {
int appVersion = getAppVersion();
//Log.v(TAG, "Saving regId on app version " + appVersion);
SharedPreferences.Editor editor = prefs.edit();
editor.putString(PROPERTY_REG_ID, regId);
editor.putInt(PROPERTY_APP_VERSION, appVersion);
long expirationTime = System.currentTimeMillis() + REGISTRATION_EXPIRY_TIME_MS;
//Log.v(TAG, "Setting registration expiry time to " + new Timestamp(expirationTime));
editor.putLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, expirationTime);
editor.commit();
}
/**
* #return Application's version code from the {#code PackageManager}.
*/
private int getAppVersion() {
try {
PackageInfo packageInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0);
return packageInfo.versionCode;
} catch (NameNotFoundException e) {
// should never happen
throw new RuntimeException("Could not get package name: " + e);
}
}
/**
* Checks if the registration has expired.
*
* <p>To avoid the scenario where the device sends the registration to the
* server but the server loses it, the app developer may choose to re-register
* after REGISTRATION_EXPIRY_TIME_MS.
*
* #return true if the registration has expired.
*/
private boolean isRegistrationExpired() {
// checks if the information is not stale
long expirationTime = prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
return System.currentTimeMillis() > expirationTime;
}
/**
* Registers the application with GCM servers asynchronously.
* <p>
* Stores the registration id, app versionCode, and expiration time in the
* application's shared preferences.
*/
private void registerBackground() {
registrationTask = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
//Log.d(TAG, "Attempt #" + i + " to register");
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(ctx);
}
String regid = gcm.register(Common.getSenderId());
// You should send the registration ID to your server over HTTP,
// so it can use GCM/HTTP or CCS to send messages to your app.
ServerUtilities.register(Common.getPreferredEmail(), regid);
// Save the regid - no need to register again.
setRegistrationId(regid);
return Boolean.TRUE;
} catch (IOException ex) {
//Log.e(TAG, "Failed to register on attempt " + i + ":" + ex);
if (i == MAX_ATTEMPTS) {
break;
}
try {
//Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
//Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
}
// increase backoff exponentially
backoff *= 2;
}
}
return Boolean.FALSE;
}
#Override
protected void onPostExecute(Boolean status) {
broadcastStatus(status);
}
}.execute();
}
private void broadcastStatus(boolean status) {
Intent intent = new Intent(Common.ACTION_REGISTER);
intent.putExtra(Common.EXTRA_STATUS, status ? Common.STATUS_SUCCESS : Common.STATUS_FAILED);
ctx.sendBroadcast(intent);
}
public void cleanup() {
if (registrationTask != null) {
registrationTask.cancel(true);
}
if (gcm != null) {
gcm.close();
}
}
}
This is Server Utilities Class:
public final class ServerUtilities {
private static final String TAG = "ServerUtilities";
private static final int MAX_ATTEMPTS = 5;
private static final int BACKOFF_MILLI_SECONDS = 2000;
private static final Random random = new Random();
/**
* Register this account/device pair within the server.
*/
public static void register(final String email, final String regId) {
//Log.i(TAG, "registering device (regId = " + regId + ")");
String serverUrl = Common.getServerUrl() + "/register";
Map<String, String> params = new HashMap<String, String>();
params.put(DataProvider.SENDER_EMAIL, email);
params.put(DataProvider.REG_ID, regId);
// Once GCM returns a registration id, we need to register it in the
// demo server. As the server might be down, we will retry it a couple
// times.
try {
post(serverUrl, params, MAX_ATTEMPTS);
} catch (IOException e) {
}
}
/**
* Unregister this account/device pair within the server.
*/
public static void unregister(final String email) {
//Log.i(TAG, "unregistering device (email = " + email + ")");
String serverUrl = Common.getServerUrl() + "/unregister";
Map<String, String> params = new HashMap<String, String>();
params.put(DataProvider.SENDER_EMAIL, email);
try {
post(serverUrl, params, MAX_ATTEMPTS);
} catch (IOException e) {
// At this point the device is unregistered from GCM, but still
// registered in the server.
// We could try to unregister again, but it is not necessary:
// if the server tries to send a message to the device, it will get
// a "NotRegistered" error message and should unregister the device.
}
}
/**
* Send a message.
*/
public static void send(String msg, String to) throws IOException {
//Log.i(TAG, "sending message (msg = " + msg + ")");
String serverUrl = Common.getServerUrl() + "/send";
Map<String, String> params = new HashMap<String, String>();
params.put(DataProvider.MESSAGE, msg);
params.put(DataProvider.SENDER_EMAIL, Common.getPreferredEmail());
params.put(DataProvider.RECEIVER_EMAIL, to);
post(serverUrl, params, MAX_ATTEMPTS);
}
/** Issue a POST with exponential backoff */
private static void post(String endpoint, Map<String, String> params, int maxAttempts) throws IOException {
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
for (int i = 1; i <= maxAttempts; i++) {
//Log.d(TAG, "Attempt #" + i);
try {
post(endpoint, params);
return;
} catch (IOException e) {
//Log.e(TAG, "Failed on attempt " + i + ":" + e);
if (i == maxAttempts) {
throw e;
}
try {
Thread.sleep(backoff);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
return;
}
backoff *= 2;
} catch (IllegalArgumentException e) {
throw new IOException(e.getMessage(), e);
}
}
}
/**
* Issue a POST request to the server.
*
* #param endpoint POST address.
* #param params request parameters.
*
* #throws IOException propagated from POST.
*/
private static void post(String endpoint, Map<String, String> params) throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("invalid url: " + endpoint);
}
StringBuilder bodyBuilder = new StringBuilder();
Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=').append(param.getValue());
if (iterator.hasNext()) {
bodyBuilder.append('&');
}
}
String body = bodyBuilder.toString();
//Log.v(TAG, "Posting '" + body + "' to " + url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
// post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
// handle the response
int status = conn.getResponseCode();
if (status != 200) {
throw new IOException("Post failed with error code " + status);
}
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}
Constants class only have sender id and url.

Can't update member variable

Somehow line mResponseText = response.body().string(); isn't writing member variable. Instead it appears to be creating and logging it locally.
Any ideas why? The more I look at it the more clueless I'm getting :(
public class Gateway {
private static final String TAG = Gateway.class.getSimpleName();
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
private String mResponseText = "[{'comment' : 'fake' , 'psn_nickname' : 'fake', 'created':'now', 'parent_class':''}]";
public Gateway (String url, String json, final Context context) {
if(isNetworkAvailable(context)) {
//if network is available build request
OkHttpClient client = new OkHttpClient();
// RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
//.post(body)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
//execute call
#Override
public void onFailure(Request request, IOException e) {
// if request failed
Toast.makeText(context, "request failed", Toast.LENGTH_LONG).show();
}
#Override
public void onResponse(Response response) throws IOException {
// if succeeded
if(response.isSuccessful()){
mResponseText = response.body().string();
Log.v(TAG, "SETTING RESPONSE");
// THIS LOGS PROPER JSON LOADED FROM NETWORK
Log.v(TAG, mResponseText);
} else {
//alertUserAboutError(context);
Toast.makeText(context, "Something wrong with response", Toast.LENGTH_LONG).show();
}
}
});
} else {
Toast.makeText(context, "Network is not available", Toast.LENGTH_LONG).show();
}
}
public String getResponse () {
Log.v(TAG, "GETTING RESPONSE");
// THIS LOGS FAKE SAMPLE JSON --- WTF???
Log.v(TAG, mResponseText);
return mResponseText;
}
// check if network is available
private boolean isNetworkAvailable(Context c) {
ConnectivityManager manager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
/*
private void alertUserAboutError(Context c) {
AlertDialogFragment dialog = new AlertDialogFragment();
dialog.show(c.getFragmentManager(), "error_dialog");
}
*/
}
Here's the code that's using this class
Gateway gateway = new Gateway(mCommentURL, "", this);
String mJsonData = gateway.getResponse();
EDIT Code update - removed extends Activity
You're calling getResponse() too early. The async operation has not completed yet and the value returned is the one you initialize there in the first place, not the one written in the Callback.
Put the code that uses the response in the Callback, or call that code from the callback.

Categories

Resources