Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package co.easimart;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import java.util.ArrayList;
import java.util.List;
/**
* A service to listen for push notifications. This operates in the same process as the parent
* application.
*
* The {@code PushService} can listen to pushes from two different sources: Google Cloud Messaging
* (GCM) or Easimart's own push network. Easimart will inspect your application's manifest at runtime and
* determine which service to use for push. We recommend using GCM for push on devices that have
* Google Play Store support. Easimart uses its own push network for apps that want to avoid a
* dependency on the Google Play Store, and for devices (like Kindles) which do not have Play Store
* support.
*
* To configure the {@code PushService} for GCM, ensure these permission declarations are present in
* your AndroidManifest.xml as children of the <manifest> element:
*
*
*
* Replace YOUR_PACKAGE_NAME in the declarations above with your application's package name. Also,
* make sure that co.easimart.GcmBroadcastReceiver and co.easimart.PushService are declared as children
* of the <application> element:
*
*
*
* Again, replace YOUR_PACKAGE_NAME with your application's package name.
*
* To configure the PushService for Easimart's push network, ensure these permission declarations are
* present in your AndroidManifest.xml as children of the <manifest> element:
*
*
*
* Note that you can configure the push service for both GCM and Easimart's network by adding all the
* declarations above to your application's manifest. In this case, Easimart will use GCM on devices
* with Play Store support and fall back to using Easimart's network on devices without Play Store
* support. If you want to customize the way your app generates Notifications for your pushes, you
* can register a custom subclass of {@link EasimartPushBroadcastReceiver}.
*
* Once push notifications are configured in the manifest, you can subscribe to a push channel by
* calling:
*
*
*
* When the client receives a push message, a notification will appear in the system tray. When the
* user taps the notification, it will broadcast the "co.easimart.push.intent.OPEN" intent.
* The {@link EasimartPushBroadcastReceiver} listens to this intent to track an app open event and
* launch the app's launcher activity. To customize this behavior override
* {@link EasimartPushBroadcastReceiver#onPushOpen(Context, Intent)}.
*/
public final class PushService extends Service {
private static final String TAG = "co.easimart.PushService";
/* package */ static final String ACTION_START_IF_REQUIRED =
"co.easimart.PushService.startIfRequired";
private static boolean loggedStartError = false;
//region ServiceLifecycleCallbacks used for testing
private static List serviceLifecycleCallbacks = null;
/* package */ interface ServiceLifecycleCallbacks {
void onServiceCreated(Service service);
void onServiceDestroyed(Service service);
}
/* package */ static void registerServiceLifecycleCallbacks(ServiceLifecycleCallbacks callbacks) {
synchronized (PushService.class) {
if (serviceLifecycleCallbacks == null) {
serviceLifecycleCallbacks = new ArrayList<>();
}
serviceLifecycleCallbacks.add(callbacks);
}
}
/* package */ static void unregisterServiceLifecycleCallbacks(
ServiceLifecycleCallbacks callbacks) {
synchronized (PushService.class) {
serviceLifecycleCallbacks.remove(callbacks);
if (serviceLifecycleCallbacks.size() <= 0) {
serviceLifecycleCallbacks = null;
}
}
}
private static void dispatchOnServiceCreated(Service service) {
Object[] callbacks = collectServiceLifecycleCallbacks();
if (callbacks != null) {
for (Object callback : callbacks) {
((ServiceLifecycleCallbacks) callback).onServiceCreated(service);
}
}
}
private static void dispatchOnServiceDestroyed(Service service) {
Object[] callbacks = collectServiceLifecycleCallbacks();
if (callbacks != null) {
for (Object callback : callbacks) {
((ServiceLifecycleCallbacks) callback).onServiceDestroyed(service);
}
}
}
private static Object[] collectServiceLifecycleCallbacks() {
Object[] callbacks = null;
synchronized (PushService.class) {
if (serviceLifecycleCallbacks == null) {
return null;
}
if (serviceLifecycleCallbacks.size() > 0) {
callbacks = serviceLifecycleCallbacks.toArray();
}
}
return callbacks;
}
//endregion
/**
* Client code should not construct a PushService directly.
*/
public PushService() {
super();
}
/* package */ static void startServiceIfRequired(Context context) {
switch (ManifestInfo.getPushType()) {
case PPNS:
EasimartInstallation installation = EasimartInstallation.getCurrentInstallation();
// If we need to downgrade the installation from GCM to PPNS, make sure to clear out the GCM
// info in the installation and send it back up to the server.
if (installation.getPushType() == PushType.GCM) {
EasimartLog.w(TAG, "Detected a client that used to use GCM and is now using PPNS.");
installation.removePushType();
installation.removeDeviceToken();
installation.saveEventually();
}
ServiceUtils.runIntentInService(
context, new Intent(PushService.ACTION_START_IF_REQUIRED), PushService.class);
break;
case GCM:
GcmRegistrar.getInstance().registerAsync();
break;
default:
if (!loggedStartError) {
EasimartLog.e(TAG, "Tried to use push, but this app is not configured for push due to: " +
ManifestInfo.getNonePushTypeLogMessage());
loggedStartError = true;
}
break;
}
}
/* package */ static void stopServiceIfRequired(Context context) {
switch (ManifestInfo.getPushType()) {
case PPNS:
context.stopService(new Intent(context, PushService.class));
break;
// We don't need to stop anything for GCM since PushService will only be short lived
}
}
private ProxyService proxy;
/**
* Client code should not call {@code onCreate} directly.
*/
@Override
public void onCreate() {
super.onCreate();
if (EasimartPlugins.Android.get().applicationContext() == null) {
EasimartLog.e(TAG, "The Easimart push service cannot start because Easimart.initialize "
+ "has not yet been called. If you call Easimart.initialize from "
+ "an Activity's onCreate, that call should instead be in the "
+ "Application.onCreate. Be sure your Application class is registered "
+ "in your AndroidManifest.xml with the android:name property of your "
+ " tag.");
stopSelf();
return;
}
switch (ManifestInfo.getPushType()) {
case PPNS:
proxy = PPNSUtil.newPPNSService(this);
break;
case GCM:
proxy = new GCMService(this);
break;
default:
EasimartLog.e(TAG, "PushService somehow started even though this device doesn't support push.");
break;
}
if (proxy != null) {
proxy.onCreate();
}
dispatchOnServiceCreated(this);
}
/**
* Client code should not call {@code onStartCommand} directly.
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
switch (ManifestInfo.getPushType()) {
case PPNS:
case GCM:
return proxy.onStartCommand(intent, flags, startId);
default:
EasimartLog.e(TAG, "Started push service even though no push service is enabled: " + intent);
ServiceUtils.completeWakefulIntent(intent);
return START_NOT_STICKY;
}
}
/**
* Client code should not call {@code onBind} directly.
*/
@Override
public IBinder onBind(Intent intent) {
throw new IllegalArgumentException("You cannot bind directly to the PushService. "
+ "Use PushService.subscribe instead.");
}
/**
* Client code should not call {@code onDestroy} directly.
*/
@Override
public void onDestroy() {
if (proxy != null) {
proxy.onDestroy();
}
dispatchOnServiceDestroyed(this);
super.onDestroy();
}
}