com.backendless.push.BackendlessPushService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android Show documentation
Show all versions of android Show documentation
Android SDK used by developers to provide Backendless API in apps.
package com.backendless.push;
import android.app.*;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.backendless.Backendless;
import com.backendless.async.callback.AsyncCallback;
import com.backendless.exceptions.BackendlessFault;
import com.backendless.messaging.PublishOptions;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class BackendlessPushService extends IntentService implements PushReceiverCallback
{
static final String TAG = "com.backendless.push.BackendlessPushService";
private static final Random random = new Random();
private static final int MAX_BACKOFF_MS = (int) TimeUnit.SECONDS.toMillis( 3600 );
private static final String TOKEN = Long.toBinaryString( random.nextLong() );
private static final String EXTRA_TOKEN = "token";
private PushReceiverCallback callback;
public BackendlessPushService()
{
this( "BackendlessPushService" );
}
public BackendlessPushService( String name )
{
super( name );
this.callback = this;
}
public BackendlessPushService( PushReceiverCallback callback )
{
super(null);
this.callback = callback;
}
/**
* At this point {@link com.backendless.push.BackendlessBroadcastReceiver}
* is still holding a wake lock
* for us. We can do whatever we need to here and then tell it that
* it can release the wakelock. This sample just does some slow work,
* but more complicated implementations could take their own wake
* lock here before releasing the receiver's.
*
* Note that when using this approach you should be aware that if your
* service gets killed and restarted while in the middle of such work
* (so the Intent gets re-delivered to perform the work again), it will
* at that point no longer be holding a wake lock since we are depending
* on SimpleWakefulReceiver to that for us. If this is a concern, you can
* acquire a separate wake lock here.
*/
@Override
protected void onHandleIntent( Intent intent )
{
try
{
handleIntent( this, intent );
}
finally
{
BackendlessBroadcastReceiver.completeWakefulIntent( intent );
}
}
public void onRegistered( Context context, String registrationId )
{
}
public void onUnregistered( Context context, Boolean unregistered )
{
}
public boolean onMessage( Context context, Intent intent )
{
return true;
}
public void onError( Context context, String message )
{
Log.e( TAG, "Error processing push message: " + message );
Toast.makeText( context, "Error processing push message: " + message, Toast.LENGTH_LONG ).show();
}
void handleIntent( Context context, Intent intent )
{
String action = intent.getAction();
switch ( action )
{
case GCMConstants.INTENT_FROM_GCM_REGISTRATION_CALLBACK:
handleRegistration( context, intent );
break;
case GCMConstants.INTENT_FROM_GCM_MESSAGE:
handleMessage( context, intent );
break;
case GCMConstants.INTENT_FROM_GCM_LIBRARY_RETRY:
handleRetry( context, intent );
break;
}
}
private void handleRetry( Context context, Intent intent )
{
String token = intent.getStringExtra( EXTRA_TOKEN );
if( !TOKEN.equals( token ) )
return;
// retry last call
if( GCMRegistrar.isRegistered( context ) )
GCMRegistrar.internalUnregister( context );
else
GCMRegistrar.internalRegister( context, GCMRegistrar.getSenderId( context ) );
}
private void handleMessage( final Context context, Intent intent )
{
try
{
boolean showPushNotification = callback.onMessage( context, intent );
if( showPushNotification )
{
CharSequence tickerText = intent.getStringExtra( PublishOptions.ANDROID_TICKER_TEXT_TAG );
CharSequence contentTitle = intent.getStringExtra( PublishOptions.ANDROID_CONTENT_TITLE_TAG );
CharSequence contentText = intent.getStringExtra( PublishOptions.ANDROID_CONTENT_TEXT_TAG );
if( tickerText != null && tickerText.length() > 0 )
{
int appIcon = context.getApplicationInfo().icon;
if( appIcon == 0 )
appIcon = android.R.drawable.sym_def_app_icon;
Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage( context.getApplicationInfo().packageName );
PendingIntent contentIntent = PendingIntent.getActivity( context, 0, notificationIntent, 0 );
Notification notification = new Notification.Builder( context )
.setSmallIcon( appIcon )
.setTicker( tickerText )
.setContentTitle( contentTitle )
.setContentText( contentText )
.setContentIntent( contentIntent )
.setWhen( System.currentTimeMillis() )
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
int customLayout = context.getResources().getIdentifier( "notification", "layout", context.getPackageName() );
int customLayoutTitle = context.getResources().getIdentifier( "title", "id", context.getPackageName() );
int customLayoutDescription = context.getResources().getIdentifier( "text", "id", context.getPackageName() );
int customLayoutImageContainer = context.getResources().getIdentifier( "image", "id", context.getPackageName() );
int customLayoutImage = context.getResources().getIdentifier( "push_icon", "drawable", context.getPackageName() );
if( customLayout > 0 && customLayoutTitle > 0 && customLayoutDescription > 0 && customLayoutImageContainer > 0 )
{
NotificationLookAndFeel lookAndFeel = new NotificationLookAndFeel();
lookAndFeel.extractColors( context );
RemoteViews contentView = new RemoteViews( context.getPackageName(), customLayout );
contentView.setTextViewText( customLayoutTitle, contentTitle );
contentView.setTextViewText( customLayoutDescription, contentText );
contentView.setTextColor( customLayoutTitle, lookAndFeel.getTextColor() );
contentView.setFloat( customLayoutTitle, "setTextSize", lookAndFeel.getTextSize() );
contentView.setTextColor( customLayoutDescription, lookAndFeel.getTextColor() );
contentView.setFloat( customLayoutDescription, "setTextSize", lookAndFeel.getTextSize() );
contentView.setImageViewResource( customLayoutImageContainer, customLayoutImage );
notification.contentView = contentView;
}
NotificationManager notificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );
notificationManager.notify( intent.getIntExtra( BackendlessBroadcastReceiver.EXTRA_MESSAGE_ID, 0 ), notification );
}
}
}
catch ( Throwable throwable )
{
Log.e( TAG, "Error processing push notification", throwable );
}
}
private void handleRegistration( final Context context, Intent intent )
{
String registrationId = intent.getStringExtra( GCMConstants.EXTRA_REGISTRATION_ID );
String error = intent.getStringExtra( GCMConstants.EXTRA_ERROR );
String unregistered = intent.getStringExtra( GCMConstants.EXTRA_UNREGISTERED );
boolean isInternal = intent.getBooleanExtra( GCMConstants.EXTRA_IS_INTERNAL, false );
// registration succeeded
if( registrationId != null )
{
if( isInternal )
{
callback.onRegistered( context, registrationId );
}
GCMRegistrar.resetBackoff( context );
GCMRegistrar.setGCMdeviceToken( context, registrationId );
registerFurther( context, registrationId );
return;
}
// unregistration succeeded
if( unregistered != null )
{
// Remember we are unregistered
GCMRegistrar.resetBackoff( context );
GCMRegistrar.setGCMdeviceToken( context, "" );
GCMRegistrar.setChannels( context, Collections.emptyList() );
GCMRegistrar.setRegistrationExpiration( context, -1 );
unregisterFurther( context );
return;
}
// Registration failed
if( error.equals( GCMConstants.ERROR_SERVICE_NOT_AVAILABLE ) )
{
int backoffTimeMs = GCMRegistrar.getBackoff( context );
int nextAttempt = backoffTimeMs / 2 + random.nextInt( backoffTimeMs );
Intent retryIntent = new Intent( GCMConstants.INTENT_FROM_GCM_LIBRARY_RETRY );
retryIntent.putExtra( EXTRA_TOKEN, TOKEN );
PendingIntent retryPendingIntent = PendingIntent.getBroadcast( context, 0, retryIntent, 0 );
AlarmManager am = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE );
am.set( AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + nextAttempt, retryPendingIntent );
// Next retry should wait longer.
if( backoffTimeMs < MAX_BACKOFF_MS )
GCMRegistrar.setBackoff( context, backoffTimeMs * 2 );
}
else
{
callback.onError( context, error );
}
}
private void registerFurther( final Context context, String GCMregistrationId )
{
final long registrationExpiration = GCMRegistrar.getRegistrationExpiration( context );
Backendless.Messaging.registerDeviceOnServer( GCMregistrationId, new ArrayList<>( GCMRegistrar.getChannels( context ) ), registrationExpiration, new AsyncCallback()
{
@Override
public void handleResponse( String registrationId )
{
GCMRegistrar.setRegistrationId( context, registrationId, registrationExpiration );
callback.onRegistered( context, registrationId );
}
@Override
public void handleFault( BackendlessFault fault )
{
callback.onError( context, "Could not register device on Backendless server: " + fault.getMessage() );
}
} );
}
private void unregisterFurther( final Context context )
{
Backendless.Messaging.unregisterDeviceOnServer( new AsyncCallback()
{
@Override
public void handleResponse( Boolean unregistered )
{
GCMRegistrar.setRegistrationId( context, "", 0 );
callback.onUnregistered( context, unregistered );
}
@Override
public void handleFault( BackendlessFault fault )
{
callback.onError( context, "Could not unregister device on Backendless server: " + fault.getMessage() );
}
} );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy