package bf.io.openshop.utils; import android.app.IntentService; import android.content.Intent; import android.support.v4.content.LocalBroadcastManager; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.RequestFuture; import com.google.android.gms.gcm.GoogleCloudMessaging; import com.google.android.gms.iid.InstanceID; import org.json.JSONArray; import org.json.JSONObject; import java.io.IOException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import bf.io.openshop.MyApplication; import bf.io.openshop.R; import bf.io.openshop.SettingsMy; import bf.io.openshop.api.EndPoints; import bf.io.openshop.api.JsonRequest; import bf.io.openshop.entities.Shop; import bf.io.openshop.entities.User; import timber.log.Timber; public class MyRegistrationIntentService extends IntentService { private static final String TAG = "GcmRegistrationService"; private static final String[] TOPICS = {"global"}; /** * Creates an IntentService. */ public MyRegistrationIntentService() { super(TAG); } @Override protected void onHandleIntent(Intent intent) { try { // [START register_for_gcm] // Initially this call goes out to the network to retrieve the token, subsequent calls // are local. // R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json. // See https://developers.google.com/cloud-messaging/android/start for details on this file. // [START get_token] InstanceID instanceID = InstanceID.getInstance(this); String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null); // [END get_token] Timber.d("GCM token obtained: %s", token); // Send token to third party only if not already registered. if (!SettingsMy.getTokenSentToServer()) { boolean success = sendRegistrationToServer(token); // Subscribe to topic channels. Not implemented now. subscribeTopics(token); // You should store a boolean that indicates whether the generated token has been // sent to your server. If the boolean is false, send the token to your server, // otherwise your server should have already received the token. SettingsMy.setTokenSentToServer(success); } // [END register_for_gcm] } catch (Exception e) { Timber.e(e, "Failed to complete token refresh"); // If an exception happens while fetching the new token or updating our registration data // on a third-party server, this ensures that we'll attempt the update at a later time. SettingsMy.setTokenSentToServer(false); } // Notify UI that registration has completed, so the progress indicator can be hidden. Intent registrationComplete = new Intent(SettingsMy.REGISTRATION_COMPLETE); LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete); } /** * Persist registration to third-party servers. * <p/> * Modify this method to associate the user's GCM registration token with any server-side account * maintained by your application. * * @param token The new token. */ private boolean sendRegistrationToServer(String token) { RequestFuture<JSONObject> future = RequestFuture.newFuture(); final Response.ErrorListener errorListener = new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { try { JSONObject errorData = new JSONObject(new String(error.networkResponse.data)); JSONArray body = errorData.getJSONArray("body"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < body.length(); i++) { sb.append(body.get(i)); sb.append("\n"); } String result = sb.toString(); Timber.e("Error message: %s", result); } catch (Exception e) { Timber.e(e, "GCM error response parsing failed"); } } }; JSONObject requestPost = new JSONObject(); try { requestPost.put("platform", "android"); requestPost.put("device_token", token); Shop shop = SettingsMy.getActualShop(); if (shop != null) { String url = String.format(EndPoints.REGISTER_NOTIFICATION, shop.getId()); JsonRequest req; User activeUser = SettingsMy.getActiveUser(); if (activeUser != null) { Timber.d("GCM registration send: authorized"); req = new JsonRequest(Request.Method.POST, url, requestPost, future, errorListener, null, activeUser.getAccessToken()); } else { Timber.d("GCM registration send: non-authorized"); req = new JsonRequest(Request.Method.POST, url, requestPost, future, errorListener); } req.setRetryPolicy(MyApplication.getDefaultRetryPolice()); req.setShouldCache(false); MyApplication.getInstance().addToRequestQueue(req, "no_cancel_tag"); } else { Timber.e("Register notification failed - null actual shop."); return false; } } catch (Exception e) { Timber.d(e, "Register notification failed."); return false; } try { // Called only on success. If request contains error, timeout will be called. JSONObject response = future.get(30, TimeUnit.SECONDS); Timber.d("GCM registration success: %s", response.toString()); return true; } catch (InterruptedException e) { Timber.e(e, "Register device api call interrupted."); errorListener.onErrorResponse(new VolleyError(e)); } catch (ExecutionException e) { Timber.e(e, "Register device api call failed."); errorListener.onErrorResponse(new VolleyError(e)); } catch (TimeoutException e) { Timber.e(e, "Register device api call timed out."); errorListener.onErrorResponse(new VolleyError(e)); } return false; } /** * Subscribe to any GCM topics of interest, as defined by the TOPICS constant. * * @param token GCM token * @throws IOException if unable to reach the GCM PubSub service */ // [START subscribe_topics] private void subscribeTopics(String token) throws IOException { // Topics not used now. // GcmPubSub pubSub = GcmPubSub.getInstance(this); // for (String topic : TOPICS) { // pubSub.subscribe(token, "/topics/" + topic, null); // } } // [END subscribe_topics] }