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

com.backendless.push.PushTemplateHelper Maven / Gradle / Ivy

package com.backendless.push;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.app.RemoteInput;
import android.util.Log;
import com.backendless.Backendless;
import com.backendless.messaging.Action;
import com.backendless.messaging.AndroidPushTemplate;
import com.backendless.messaging.PublishOptions;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;


public class PushTemplateHelper
{
  private static Map pushNotificationTemplates;

  public static Map getPushNotificationTemplates()
  {
    if (pushNotificationTemplates == null)
      PushTemplateHelper.restorePushTemplates();

    return pushNotificationTemplates;
  }

  public static void setPushNotificationTemplates( Map pushNotificationTemplates, byte[] rawTemplates )
  {
    PushTemplateHelper.pushNotificationTemplates = Collections.unmodifiableMap( pushNotificationTemplates );
    savePushTemplates( rawTemplates );
  }

  private static void savePushTemplates( byte[] rawBytes )
  {
    try
    {
      JSONArray jsonArray = new JSONArray( new String( rawBytes) );
      JSONObject templates = jsonArray.getJSONObject( 1 );
      Backendless.savePushTemplates( templates.toString() );
    }
    catch( JSONException e )
    {
      Log.w( PushTemplateHelper.class.getSimpleName(), "Cannot deserialize AndroidPushTemplate to JSONObject.", e );
    }
  }

  static Bundle prepareMessageBundle(final Bundle rawMessageBundle, final AndroidPushTemplate template, final int notificationId )
  {
    Bundle newBundle = new Bundle( );

    if( template.getCustomHeaders() != null && !template.getCustomHeaders().isEmpty() )
    {
      for( Map.Entry header : template.getCustomHeaders().entrySet() )
        newBundle.putString( header.getKey(), header.getValue() );
    }

    newBundle.putAll( rawMessageBundle );

    String contentTitle = rawMessageBundle.getString( PublishOptions.ANDROID_CONTENT_TITLE_TAG );
    String summarySubText = rawMessageBundle.getString( PublishOptions.ANDROID_SUMMARY_SUBTEXT_TAG );

    contentTitle = contentTitle != null ? contentTitle : template.getContentTitle();
    summarySubText = summarySubText != null ? summarySubText : template.getSummarySubText();

    newBundle.putString( PublishOptions.ANDROID_CONTENT_TITLE_TAG, contentTitle );
    newBundle.putString( PublishOptions.ANDROID_SUMMARY_SUBTEXT_TAG, summarySubText );
    newBundle.putInt( PublishOptions.NOTIFICATION_ID, notificationId );
    newBundle.putString( PublishOptions.TEMPLATE_NAME, template.getName() );

    return newBundle;
  }

  static Notification convertFromTemplate( final Context context, final AndroidPushTemplate template, final Bundle newBundle, int notificationId )
  {
    Context appContext = context.getApplicationContext();
    // Notification channel ID is ignored for Android 7.1.1 (API level 25) and lower.

    String messageText = newBundle.getString( PublishOptions.MESSAGE_TAG );
    
    String contentTitle = newBundle.getString( PublishOptions.ANDROID_CONTENT_TITLE_TAG );
    contentTitle = contentTitle != null ? contentTitle : template.getContentTitle();
    
    String summarySubText = newBundle.getString( PublishOptions.ANDROID_SUMMARY_SUBTEXT_TAG );
    summarySubText = summarySubText != null ? summarySubText : template.getSummarySubText();
    
    String largeIcon = newBundle.getString( PublishOptions.ANDROID_LARGE_ICON_TAG );
    largeIcon = largeIcon != null ? largeIcon : template.getLargeIcon();
  
    String attachmentUrl = newBundle.getString( PublishOptions.ANDROID_ATTACHMENT_URL_TAG );
    attachmentUrl = attachmentUrl != null ? attachmentUrl : template.getAttachmentUrl();
  
  
    NotificationCompat.Builder notificationBuilder;
    // android.os.Build.VERSION_CODES.O == 26
    if( android.os.Build.VERSION.SDK_INT > 25 )
    {
      NotificationChannel notificationChannel = getOrCreateNotificationChannel( appContext, template );

      notificationBuilder = new NotificationCompat.Builder( appContext, notificationChannel.getId() );

      if( template.getBadge() != null &&
          ( template.getBadge() == NotificationCompat.BADGE_ICON_SMALL || template.getBadge() == NotificationCompat.BADGE_ICON_LARGE ) )
        notificationBuilder.setBadgeIconType( template.getBadge() );
      else
        notificationBuilder.setBadgeIconType( NotificationCompat.BADGE_ICON_NONE );

      if( template.getBadgeNumber() != null )
        notificationBuilder.setNumber( template.getBadgeNumber() );

      if( template.getCancelAfter() != null && template.getCancelAfter() != 0 )
        notificationBuilder.setTimeoutAfter( template.getCancelAfter()*1000 );
    }
    else
    {
      notificationBuilder = new NotificationCompat.Builder( appContext );

      if( template.getPriority() != null && template.getPriority() > 0 && template.getPriority() < 6 )
        notificationBuilder.setPriority( template.getPriority() - 3 );
      else
        notificationBuilder.setPriority( NotificationCompat.PRIORITY_DEFAULT );

      if( notificationBuilder.getPriority() > NotificationCompat.PRIORITY_LOW )
        notificationBuilder.setSound( PushTemplateHelper.getSoundUri( appContext, template.getSound() ), AudioManager.STREAM_NOTIFICATION );

      if( template.getVibrate() != null && template.getVibrate().length > 0 && notificationBuilder.getPriority() > NotificationCompat.PRIORITY_LOW )
      {
        long[] vibrate = new long[ template.getVibrate().length ];
        int index = 0;
        for( long l : template.getVibrate() )
          vibrate[ index++ ] = l;

        notificationBuilder.setVibrate( vibrate );
      }
    }

    if( attachmentUrl != null )
    {
      try
      {
        InputStream is = (InputStream) new URL( attachmentUrl ).getContent();
        Bitmap bitmap = BitmapFactory.decodeStream( is );

        if( bitmap != null )
          notificationBuilder.setStyle( new NotificationCompat.BigPictureStyle().bigPicture( bitmap ) );
        else
          Log.i( PushTemplateHelper.class.getSimpleName(), "Cannot convert rich media for notification into bitmap." );
      }
      catch( IOException e )
      {
        Log.e( PushTemplateHelper.class.getSimpleName(), "Cannot receive rich media for notification." );
      }
    }
    else if( messageText.length() > 35 )
    {
      NotificationCompat.BigTextStyle bigText = new NotificationCompat.BigTextStyle()
              .setBigContentTitle( contentTitle )
              .setSummaryText( summarySubText )
              .bigText( messageText );
      notificationBuilder.setStyle( bigText );
    }

    if( largeIcon != null )
    {
      if (largeIcon.startsWith( "http" ))
      {
        try
        {
          InputStream is = (InputStream) new URL( largeIcon ).getContent();
          Bitmap bitmap = BitmapFactory.decodeStream( is );

          if( bitmap != null )
            notificationBuilder.setLargeIcon( bitmap );
          else
            Log.i( PushTemplateHelper.class.getSimpleName(), "Cannot convert Large Icon into bitmap." );
        }
        catch( IOException e )
        {
          Log.e( PushTemplateHelper.class.getSimpleName(), "Cannot receive bitmap for Large Icon." );
        }
      }
      else
      {
        int largeIconResource = appContext.getResources().getIdentifier( largeIcon, "drawable", appContext.getPackageName() );
        if (largeIconResource != 0)
        {
          Bitmap bitmap = BitmapFactory.decodeResource(appContext.getResources(), largeIconResource);
          notificationBuilder.setLargeIcon( bitmap );
        }
      }
    }

    int icon = 0;

    // try to get icon from template
    if( template.getIcon() != null )
    {
      icon = appContext.getResources().getIdentifier( template.getIcon(), "mipmap", appContext.getPackageName() );

      if( icon == 0 )
        icon = appContext.getResources().getIdentifier( template.getIcon(), "drawable", appContext.getPackageName() );
    }

    // try to get default icon
    if( icon == 0 )
    {
      icon = context.getApplicationInfo().icon;
      if( icon == 0 )
        icon = android.R.drawable.sym_def_app_icon;
    }

    if( icon != 0 )
        notificationBuilder.setSmallIcon( icon );

    if (template.getLightsColor() != null && template.getLightsOnMs() != null && template.getLightsOffMs() != null)
      notificationBuilder.setLights(template.getLightsColor()|0xFF000000, template.getLightsOnMs(), template.getLightsOffMs());

    if (template.getColorCode() != null)
      notificationBuilder.setColor( template.getColorCode()|0xFF000000 );

    if (template.getCancelOnTap() != null)
      notificationBuilder.setAutoCancel( template.getCancelOnTap() );
    else
      notificationBuilder.setAutoCancel( false );

    notificationBuilder
            .setShowWhen( true )
            .setWhen( System.currentTimeMillis() )
            .setContentTitle( contentTitle != null ? contentTitle : template.getContentTitle() )
            .setSubText( summarySubText != null ? summarySubText : template.getSummarySubText() )
            .setContentText( messageText );
  
    Intent notificationIntent;
    if (template.getActionOnTap() == null || template.getActionOnTap().isEmpty())
      notificationIntent = appContext.getPackageManager().getLaunchIntentForPackage(appContext.getPackageName());
    else
    {
      notificationIntent = new Intent("ActionOnTap");
      notificationIntent.setClassName(appContext, template.getActionOnTap());
    }
  
    notificationIntent.putExtras(newBundle);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(appContext, notificationId * 3, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
  
    // user should use messageId and tag(templateName) to cancel notification.
    notificationBuilder.setContentIntent(contentIntent);

    if( template.getActions() != null )
    {
      List actions = createActions( appContext, template.getActions(), newBundle, notificationId );
      for( NotificationCompat.Action action : actions )
        notificationBuilder.addAction( action );
    }

    return notificationBuilder.build();
  }

  static Uri getSoundUri( Context context, String resource )
  {
    Uri soundUri;
    if( resource != null && !resource.isEmpty() )
    {
      int soundResource = context.getResources().getIdentifier( resource, "raw", context.getPackageName() );
      soundUri = Uri.parse( "android.resource://" + context.getPackageName() + "/" + soundResource );
    }
    else
      soundUri = RingtoneManager.getDefaultUri( RingtoneManager.TYPE_NOTIFICATION );

    return soundUri;
  }

  static private List createActions( final Context appContext, final Action[] actions, final Bundle bundle, int notificationId )
  {
    List notifActions = new ArrayList<>();

    int i = 1;
    for( Action a : actions )
    {
      Intent actionIntent = new Intent( a.getTitle() );
      actionIntent.setClassName( appContext, a.getId() );
      actionIntent.putExtras( bundle );
      actionIntent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );

      // user should use messageId and tag(templateName) to cancel notification.

      PendingIntent pendingIntent = PendingIntent.getActivity( appContext, notificationId * 3 + i++, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT );

      NotificationCompat.Action.Builder actionBuilder = new NotificationCompat.Action.Builder( 0, a.getTitle(), pendingIntent );

      if( a.getOptions() == 1 )
      {
        RemoteInput remoteInput = new RemoteInput.Builder( PublishOptions.INLINE_REPLY ).build();
        actionBuilder.setAllowGeneratedReplies( true ).addRemoteInput( remoteInput );
      }
      notifActions.add( actionBuilder.build() );
    }

    return notifActions;
  }

  static public void deleteNotificationChannel( Context context )
  {
    if( android.os.Build.VERSION.SDK_INT < 26 )
      return;

    NotificationManager notificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );
    List notificationChannels = notificationManager.getNotificationChannels();
    for (NotificationChannel notifChann : notificationChannels)
      notificationManager.deleteNotificationChannel( notifChann.getId() );
  }

  static public NotificationChannel getNotificationChannel( final Context context, final String templateName )
  {
    final String channelId = Backendless.getApplicationId() + ":" + templateName;
    NotificationManager notificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );
    return notificationManager.getNotificationChannel( channelId );
  }

  static public NotificationChannel getOrCreateNotificationChannel( Context context, final AndroidPushTemplate template )
  {
    final String channelId = Backendless.getApplicationId() + ":" + template.getName();
    NotificationManager notificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );

    NotificationChannel notificationChannel = notificationManager.getNotificationChannel( channelId );

    if( notificationChannel != null )
      return notificationChannel;

    notificationChannel = new NotificationChannel( channelId, template.getName(), NotificationManager.IMPORTANCE_DEFAULT );
    PushTemplateHelper.updateNotificationChannel( context, notificationChannel, template );
    notificationManager.createNotificationChannel( notificationChannel );
    return notificationChannel;
  }

  static private NotificationChannel updateNotificationChannel( Context context, NotificationChannel notificationChannel, final AndroidPushTemplate template )
  {
    if( template.getShowBadge() != null )
      notificationChannel.setShowBadge( template.getShowBadge() );

    if( template.getPriority() != null && template.getPriority() > 0 && template.getPriority() < 6 )
      notificationChannel.setImportance( template.getPriority() ); // NotificationManager.IMPORTANCE_DEFAULT

    AudioAttributes audioAttributes = new AudioAttributes.Builder()
            .setUsage( AudioAttributes.USAGE_NOTIFICATION_RINGTONE )
            .setContentType( AudioAttributes.CONTENT_TYPE_SONIFICATION )
            .setFlags( AudioAttributes.FLAG_AUDIBILITY_ENFORCED )
            .setLegacyStreamType( AudioManager.STREAM_NOTIFICATION )
            .build();

    notificationChannel.setSound( PushTemplateHelper.getSoundUri( context, template.getSound() ), audioAttributes );

    if (template.getLightsColor() != null)
    {
      notificationChannel.enableLights( true );
      notificationChannel.setLightColor( template.getLightsColor()|0xFF000000 );
    }

    if( template.getVibrate() != null && template.getVibrate().length > 0 )
    {
      long[] vibrate = new long[ template.getVibrate().length ];
      int index = 0;
      for( long l : template.getVibrate() )
        vibrate[ index++ ] = l;

      notificationChannel.enableVibration( true );
      notificationChannel.setVibrationPattern( vibrate );
    }

    return notificationChannel;
  }

  static void showNotification( final Context context, final Notification notification, final String tag, final int notificationId )
  {
    final NotificationManagerCompat notificationManager = NotificationManagerCompat.from( context.getApplicationContext() );
    Handler handler = new Handler( Looper.getMainLooper() );
    handler.post( new Runnable()
    {
      @Override
      public void run()
      {
        notificationManager.notify( tag, notificationId, notification );
      }
    } );
  }

  private static void restorePushTemplates()
  {
    String rawTemplates = Backendless.getPushTemplatesAsJson();

    if (rawTemplates == null)
    {
      pushNotificationTemplates = Collections.emptyMap();
      return;
    }

    Map templates;
    try
    {
      templates = (Map) weborb.util.io.Serializer.fromBytes( rawTemplates.getBytes(), weborb.util.io.Serializer.JSON, false );
      pushNotificationTemplates = Collections.unmodifiableMap( templates);
    }
    catch( IOException e )
    {
      pushNotificationTemplates = Collections.emptyMap();
      Log.w( PushTemplateHelper.class.getSimpleName(), "Cannot deserialize AndroidPushTemplate to JSONObject.", e );
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy