All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.parse.GCMService Maven / Gradle / Ivy

Go to download

A library that gives you access to the powerful Parse cloud platform from your Android app.

There is a newer version: 1.17.3
Show newest version
/*
 * Copyright (c) 2015-present, Parse, LLC.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
package com.parse;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Proxy Service while running in GCM mode.
 *
 * We use an {@link ExecutorService} so that we can operate like a ghetto
 * {@link android.app.IntentService} where all incoming {@link Intent}s will be handled
 * sequentially.
 */
/** package */ class GCMService implements ProxyService {
  private static final String TAG = "GCMService";

  public static final String REGISTER_RESPONSE_ACTION =
      "com.google.android.c2dm.intent.REGISTRATION";
  public static final String RECEIVE_PUSH_ACTION =
      "com.google.android.c2dm.intent.RECEIVE";

  private final WeakReference parent;
  private ExecutorService executor;

  /* package */ GCMService(Service parent) {
    this.parent = new WeakReference<>(parent);
  }

  @Override
  public void onCreate() {
    executor = Executors.newSingleThreadExecutor();
  }

  @Override
  public void onDestroy() {
    if (executor != null) {
      executor.shutdown();
      executor = null;
    }
  }

  @Override
  public int onStartCommand(final Intent intent, int flags, final int startId) {
    executor.execute(new Runnable() {
      @Override
      public void run() {
        try {
          onHandleIntent(intent);
        } finally {
          ServiceUtils.completeWakefulIntent(intent);
          stopParent(startId); // automatically stops service if this is the last outstanding task
        }
      }
    });

    return Service.START_NOT_STICKY;
  }

  @Override
  public IBinder onBind(Intent intent) {
    return null;
  }

  private void onHandleIntent(Intent intent) {
    if (intent != null) {
      String action = intent.getAction();
      if (REGISTER_RESPONSE_ACTION.equals(action)) {
        handleGcmRegistrationIntent(intent);
      } else if (RECEIVE_PUSH_ACTION.equals(action)) {
        handleGcmPushIntent(intent);
      } else {
        PLog.e(TAG, "PushService got unknown intent in GCM mode: " + intent);
      }
    }
  }

  private void handleGcmRegistrationIntent(Intent intent) {
    try {
      // Have to block here since GCMService is basically an IntentService, and the service is
      // may exit before async handling of the registration is complete if we don't wait for it to
      // complete.
      GcmRegistrar.getInstance().handleRegistrationIntentAsync(intent).waitForCompletion();
    } catch (InterruptedException e) {
      // do nothing
    }
  }

  private void handleGcmPushIntent(Intent intent) {
    String messageType = intent.getStringExtra("message_type");
    if (messageType != null) {
      /*
       * The GCM docs reserve the right to use the message_type field for new actions, but haven't
       * documented what those new actions are yet. For forwards compatibility, ignore anything
       * with a message_type field.
       */
      PLog.i(TAG, "Ignored special message type " + messageType + " from GCM via intent " + intent);
    } else {
      String pushId = intent.getStringExtra("push_id");
      String timestamp = intent.getStringExtra("time");
      String dataString = intent.getStringExtra("data");
      String channel = intent.getStringExtra("channel");

      JSONObject data = null;
      if (dataString != null) {
        try {
          data = new JSONObject(dataString);
        } catch (JSONException e) {
          PLog.e(TAG, "Ignoring push because of JSON exception while processing: " + dataString, e);
          return;
        }
      }

      PushRouter.getInstance().handlePush(pushId, timestamp, channel, data);
    }
  }

  /**
   * Stop the parent Service, if we're still running.
   */
  private void stopParent(int startId) {
    Service p = parent.get();
    if (p != null) {
      p.stopSelf(startId);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy