Showing posts with label notifications. Show all posts
Showing posts with label notifications. Show all posts

Friday, October 5, 2018

When to handle Socket.io notifications?

Leave a Comment

I am developing an IOS social application that is written in SWIFT.

The backend is PHP, MySQL (for event handling), + a bit of NodeJS, Socket.io (for realtime chat and notifications)


I have made the chat successfully:

When the user sends a message the Socket.io server handles it the following way:

  • it inserts the datas to the database
  • if successful then emits the message to all the participant users

/ so for this the backend is only the Socket.io server, which handles the database aswell


Works fine.

But then there are events that are not meant to be real time, but still I want to send a notification to the given user with Socket.io

for example: if a post has been liked, then send a noti to the posts owner

I have already written the PHP files for saving the like in the database, but

How should I do the notification part, safe?


I have came up with 3 ideas:

  1. The app sends a web request to my PHP+MySQL backend, it handles the data there, then after returning back "success", the application (SWIFT) sends a notification to the post owner (via Socket.io XCode pod)
func likePost(postId : Int, completion: @escaping (ActionResult?)->()){          let connectUrl = URL(string: appSettings.url + "/src/main/like.php")         var request = URLRequest(url: connectUrl!)         request.httpMethod = "POST"         let postString = "userId=\(userId)&session=\(session)&pId=\(postId)"         request.httpBody = postString.data(using: String.Encoding.utf8)           let task = URLSession.shared.dataTask(with: request) {             (data: Data?, response: URLResponse?, error: Error?) in              if error != nil {                 return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))             }             do {                  let responseJson = try JSONSerialization.jsonObject(with: data!, options: [])                 if let responseArray = responseJson as? [String: Any] {                      let responseStatus = responseArray["status"] as? String                     let responseTitle = responseArray["title"] as? String                     let responseMessage = responseArray["message"] as? String                       if responseStatus != "1" {                         return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))                     }                      // SUCCESS, SEND NOTI WITH SOCKET.IO                      socket.emit("notification_likedPost", ["postId": postId)                      return completion(ActionResult(type: 1, title: "success", message: "yay"))                  }             } catch {                 return completion(ActionResult(type: 0, code: 0, title: "error", message: "something went wrong"))             }         }         task.resume()     } 
  1. same, but after returning back "success" from the PHP, itself (the PHP file) handles the Socket.IO notification emitting as well (I think this is not possible, I haven't found any PHP->Socket.io plugins..)

-

  1. The app does not send anything to my web PHP+MySQL file, instead it sends the whole "like" process to my NodeJs, Socket.IO server, it handles it there, saves it to the database, then emits the notifications (Just like the real time chat part, but this would be a lot work because I have already written all the other code in PHP files)

The first case is the most ideal for me, but I am scared that it would be hackable..

Because if I do it the first way, the backend NodeJs+Socket.io server won't check if the liking process was successful (because it was checked client-sided)

so it is likely that anyone could send fake "post like" notifications, like a billion times.


Then maybe the second option would be great as well, so that back-end handles both checking, and notification sending, but sadly there's no Socket.io plugin for PHP

3 Answers

Answers 1

It would be much more simpler to ...

Forget PHP, Go full Nodejs:

Express (you can also combine it with handlebars & i18n for multi-language purpose)

With express you can build a router for incoming requests (GET,PUT,POST,...)

This means that you can use it to render pages with server-side dynamic data

const express = require('express'); const exphbs = require('express-handlebars'); const app = express();  // Register Handlebars view engine app.engine('handlebars', exphbs()); // Use Handlebars view engine app.set('view engine', 'handlebars');  var visit_counter = 0;  app.get('/', (req, res) => {   var time_stamp = Date.now(); visit_counter++   res.render('index',{"timestamp":time_stamp,"visits":visit_counter}); });  app.listen(3000, () => {   console.log('Example app is running → PORT 3000'); }); 

The views/index.hbs file would look like this :

<!doctype html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Example App</title> </head> <body>   <p> Current Time : {{timestamp}} </p>  <p> Total Visits : {{visits}} </p>  </body> </html> 

This above part is an example of server-side data being rendered in the final html.


Socket.io (if you want more than 1 instance of the server running, no problem, lookup socket.io-redis)

You can combine express with socket.io in different ways, you could even use cookie-based authentication for your socket protocol. so when an event is coming in you could actually tell 100% if its a legit user and its user-id.


To prevent the spam of likes... you have to control them somehow. You should store the action of the like, so it cant be repeated more than once for the same post (so user-id & post-id seem to be the important variables here)



Here comes the update :

Since you made quite clear that you want a php & nodejs combo :

Redis is an in-memory data structure store which can be used as a database, a cache and a message broker.

PHPRedis @Github

Redis PubSub with PHP and Node.JS

A quick example of Node.js reading PHP session on Redis

Using Redis, you can easily listen to php events from your nodejs instance.

I suggest that you also think about the future scaling of your system and give a try at learning more nodejs to be able to move on from php.

Answers 2

I understand your concern as your whole project has more concentration of PHP code as compared to other frameworks/languages. In order to rectify your problem, here is the Socket.io implementation for PHP v5.3 and above https://github.com/walkor/phpsocket.io.

With the help of this, you can use socket.io library in your PHP code. Below you can see an example of using Socket.io library in PHP.

use Workerman\Worker; use PHPSocketIO\SocketIO;  // listen port 2020 for socket.io client $io = new SocketIO(2020); $io->on('connection', function($socket){     $socket->addedUser = false;     // when the client emits 'new message', this listens and executes     $socket->on('new message', function ($data)use($socket){         // we tell the client to execute 'new message'         $socket->broadcast->emit('new message', array(             'username'=> $socket->username,             'message'=> $data         ));     });     // when the client emits 'add user', this listens and executes     $socket->on('add user', function ($username) use($socket){         global $usernames, $numUsers;         // we store the username in the socket session for this client         $socket->username = $username;         // add the client's username to the global list         $usernames[$username] = $username;         ++$numUsers;         $socket->addedUser = true;         $socket->emit('login', array(              'numUsers' => $numUsers         ));         // echo globally (all clients) that a person has connected         $socket->broadcast->emit('user joined', array(             'username' => $socket->username,             'numUsers' => $numUsers         ));     });     // when the client emits 'typing', we broadcast it to others     $socket->on('typing', function () use($socket) {         $socket->broadcast->emit('typing', array(             'username' => $socket->username         ));     });     // when the client emits 'stop typing', we broadcast it to others     $socket->on('stop typing', function () use($socket) {         $socket->broadcast->emit('stop typing', array(             'username' => $socket->username         ));     });     // when the user disconnects.. perform this     $socket->on('disconnect', function () use($socket) {         global $usernames, $numUsers;         // remove the username from global usernames list         if($socket->addedUser) {             unset($usernames[$socket->username]);             --$numUsers;            // echo globally that this client has left            $socket->broadcast->emit('user left', array(                'username' => $socket->username,                'numUsers' => $numUsers             ));         }    }); });  Worker::runAll(); 

Answers 3

You can create multiple web sockets channel. In your case, you have added one using socket.io in NodeJS. You can add another channel through php way.

You can listen to that channel the same way your are listening from NodeJS.

Few handy links 1. http://php.net/manual/en/book.sockets.php 2. How to create websockets server in PHP

Read More

Thursday, March 29, 2018

notification disappears after showing

Leave a Comment

We have code similar to the following in our app

    val pendingIntent = PendingIntent.getActivity(ctx, id.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT)     val builder = NotificationCompat.Builder(ctx, Channel.TEST_CHANNEL.channelId)     builder.setTicker(tickerText)             .setContentTitle(contentTitle)             .setContentText(contentText)             .setVibrate(vibrate)             .setSmallIcon(icon)             .setAutoCancel(true)             .setLights(-0xff0100, 300, 1000)             .setSound(uri)             .setContentIntent(pendingIntent)             .setStyle(NotificationCompat.BigTextStyle().bigText(contentText))             .addAction(R.drawable.ic_notification, ctx.getString(R.string.notification), piAction)      val notification = builder.build()     val nf = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager     nf.notify(NOTIFICATION_TAG, id.toInt(), notification) } 

Starting recently we noticed that notifications on some device running Android 8+ started disappearing briefly after being shown, without user's interaction. Setting auto-cancel to false helps, but the user experience degrades.

The id is a unique item id from the database. This may be important thing to note - technically we can have a notification with such id be shown, removed/canceleld by user, and later some time used again for a similar notification with the same id. Can this be the reason?

4 Answers

Answers 1

Only thing I found uncertain is NotificationCompat.Builder

Android oreo now uses Notification.Builder instead of NotificationCompat.Builder.

Might be you have to check android version like:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {          //Use Notification.Builder                   } else {          // Use NotificationCompat.Builder.          } 

I don't think unique id will be an issue for disappearing notification.

Google has created open source sample for this new changes. Please refer to it for more info.

https://github.com/googlesamples/android-NotificationChannels

Answers 2

We've updated the support libs and tried the following method on builder for luck:

 builder.setTicker(tickerText)         ...         .setTimeoutAfter(-1)         ... 

Setting this param to a positive value delayed the notification disappearing by that amount of time (so it did affect). Thus we tried a negative number, the notifications seem to stay there now.

I couldn't find any reasonable documentation explaining this, so this answer is not 100%, but keeping it here for now for others to try and see if it helps them.

Answers 3

For the newest version of Android you have to validate which version are you using:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {         //Use Notification.Builder          Notification notification = new Notification.Builder(Main.this)                     /* Make app open when you click on the notification. */                     .setContentIntent(PendingIntent.getActivity(                             Main.this,                             Main.this.i,                             new Intent(Main.this, Main.class),                             PendingIntent.FLAG_CANCEL_CURRENT))                     .setContentTitle(contentTitle)                     .setAutoCancel(true)                     .setContentText(contentText)                     .setSmallIcon(icon)drawn white.                     //.setColor(Color.RED)                     .build();             final NotificationManager notificationManager =                     (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);             notificationManager.notify(Main.this.i, notification);    } else { // Use NotificationCompat.Builder.     val pendingIntent = PendingIntent.getActivity(ctx, id.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT)     val builder = NotificationCompat.Builder(ctx, Channel.TEST_CHANNEL.channelId)     builder.setTicker(tickerText)             .setContentTitle(contentTitle)             .setContentText(contentText)             .setVibrate(vibrate)             .setSmallIcon(icon)             .setAutoCancel(true)             .setLights(-0xff0100, 300, 1000)             .setSound(uri)             .setContentIntent(pendingIntent)             .setStyle(NotificationCompat.BigTextStyle().bigText(contentText))             .addAction(R.drawable.ic_notification, ctx.getString(R.string.notification), piAction)      val notification = builder.build()     val nf = ctx.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager     nf.notify(NOTIFICATION_TAG, id.toInt(), notification) } 

You can try replacing your code for that one.

Explanation:

NotificationCompat.Builder This constructor was deprecated in API level 26.1.0. use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.

Notification.Builder your app supports versions of Android as old as API level 4, you can instead use NotificationCompat.Builder, available in the Android Support library.

Answers 4

.setAutoCancel(false)

May be it will work for you.

Read More

Wednesday, November 22, 2017

Android Notification bar buttons become not responsive

Leave a Comment

I am working on an app where I have a service that should always run in the background. This service is responsible for a Notification bar that should always be visible. The notification bar has 2 buttons, where the 1st one is for grabbing some data and storing it and the 2nd one should open an activity that will show all the data. I encountered a problem where when I close the application and then press the notification button that starts an activity after that activity starts, my notification buttons stop responding. Note that both buttons work fine before the point where the 2nd button click starts the activity.

Here is a template code for my notification service and for notification bar button handler

service that handles the Notification bar

   public class NotificationBarService extends Service {          private int notificationID;           @Override         public IBinder onBind(Intent intent){             return null;         }          @Override         public int onStartCommand(Intent intent, int flags, int startId){               notificationID = new Random().nextInt();              RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);             contentView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);             contentView.setTextViewText(R.id.title, "Custom notification");             contentView.setTextViewText(R.id.text, "This is a custom layout");               //Handle the button for showing bookmarks on custom notification             Intent buttonsIntent2 = new Intent(this, NotificationBarButtonActivityHandler.class);             buttonsIntent2.putExtra(PENDING_ACTION, SHOW_BOOKMARKS);             contentView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton, PendingIntent.getActivity(this, 0, buttonsIntent2, 0));               //Handle the button for adding bookmark on custom notification             Intent buttonsIntent = new Intent(this, NotificationBarButtonActivityHandler.class);             buttonsIntent.putExtra(PENDING_ACTION, REGISTER_BOOKMARK);             contentView.setOnClickPendingIntent(R.id.notificationBarAddBookmarkFromChromeButton, PendingIntent.getActivity(this, 1, buttonsIntent, 0));               RemoteViews notificationView = new RemoteViews(getPackageName(),                     R.layout.custom_notification);               Intent switchIntent = new Intent(this, NotificationBarService.class);             PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 0,                     switchIntent, 0);              notificationView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton,                     pendingSwitchIntent);               NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)                     .setContent(contentView)                     .setSmallIcon(R.drawable.notification_small_icon)                     .setOngoing(true);              Notification notification = mBuilder.build();              startForeground(notificationID, notification);              return START_STICKY;         }           @Override         public void onDestroy(){             super.onDestroy();              stopForeground(true);          }     } 

Class that handles the button press on Notification bar

public class NotificationBarButtonActivityHandler extends Activity {      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);          String action = (String) getIntent().getExtras().get(NotificationBarService.PENDING_ACTION);          if (action != null) {             if (action.equals(NotificationBarService.REGISTER_BOOKMARK)){                 CustomLogger.log("---------------- BUTTON FOR COLLECT DATA WAS PRESSED!!!");                  //Does something here             }             else if(action.equals(NotificationBarService.SHOW_BOOKMARKS)){                 CustomLogger.log("---------------- BUTTON FOR SHOW DATA WAS PRESSSED!!!");                   //Notification bar buttons start not responding right after                 //this is executed. Note that this problem only occurs if I close the app                 //and press the notification button to execute this code.                 //Otherwise this works just fine.                 Intent intent2;                 intent2 = new Intent(this, BookmarkDisplayActivity.class);                 startActivity(intent2);             }         }           finish();     } } 

So basically if I close the application and remove the code that starts the activity, both buttons work as expected but as soon as I start the activity, both buttons stop working.

1 Answers

Answers 1

Ok, I finally solved the issue that I was having with changing the way that I handle button presses. This is what I got now and it works as expected.

In NotificationBarService this is how I handle the listeners for the buttons

Intent addBookmarkIntent = new Intent(this, NotificationBarButtonListener.class);             addBookmarkIntent.setAction(ADD_BOOKMARK_ACTION);             PendingIntent pendingAddBookmarkIntent = PendingIntent.getBroadcast(this, 0, addBookmarkIntent, 0);             contentView.setOnClickPendingIntent(R.id.notificationBarAddBookmarkFromChromeButton, pendingAddBookmarkIntent);              Intent showBookmarkIntent = new Intent(this, NotificationBarButtonListener.class);             showBookmarkIntent.setAction(SHOW_BOOKMARK_ACTION);             PendingIntent pendingShowBookmarkIntent = PendingIntent.getBroadcast(this, 0, showBookmarkIntent, 0);             contentView.setOnClickPendingIntent(R.id.notificationBarShowBookmarksButton, pendingShowBookmarkIntent); 

and then I receive a broadcast even and handle it like this

public static class NotificationBarButtonListener extends BroadcastReceiver {         @Override         public void onReceive(Context context, Intent intent) {              final String action = intent.getAction();             if(action.equals(ADD_BOOKMARK_ACTION)){                 CustomLogger.log("---------------- BUTTON FOR REGISTER BOOKMARK WAS PRESSED!!! ");               }             else if(action.equals(SHOW_BOOKMARK_ACTION)){                 CustomLogger.log("---------------- BUTTON FOR SHOW BOOKMARK WAS PRESSSED!!!");              }          }     } 

Note that this required me to add the following line to my manifest

<receiver android:name=".NotificationBarService$NotificationBarButtonListener"/> 
Read More

Thursday, October 12, 2017

Android 5+ custom notification XML layout with RemoteViews, set correct icon tint for ImageButton

Leave a Comment

My app is using a custom Notification layout with RemoteViews.

To display text, the layout is using the following system styles:

android:TextAppearance.Material.Notification.Title android:TextAppearance.Material.Notification

This works fine.

However, the TextAppearance style can't be used to set the value of android:tint, so I had to hardcode the color.

To my best knowledge, there's no special system style for setting notification ImageButton tint.

Hardcoded colors work fine on the current Android 5+ systems, but some users install custom ROMs with custom dark themes, and the notification looks wrong, i.e. black icons on black background.

Is there any way to get the system notification icon / imagebutton color, and apply it from an XML layout?

Or maybe there's another way to achieve this?

5 Answers

Answers 1

Sorry, But as per my knowledge custom ROM's have separate system designs,configurations and that are not official as well.

So,supporting Custom ROM without knowledge about its design is not possible. And android APIs are for supporting official ROM's.

Hope it Helps!!

Answers 2

Try this example :

* Def :*

public static Bitmap icon ;  icon = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.YOUR_IMAGE);        mBuilder = new NotificationCompat.Builder(this);         mBuilder.setShowWhen(false);         mBuilder.setDefaults(Notification.DEFAULT_ALL);         mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);         mBuilder.setSmallIcon(R.drawable.image1);         mBuilder.setContentText("this text not visible");         mBuilder.setLargeIcon(icon);         mBuilder.setPriority(Notification.PRIORITY_DEFAULT);         mBuilder.setContent(contentNotifySmall); // ORI         //mBuilder.setAutoCancel(false);         mBuilder.setCustomBigContentView(contentNotify); 

Answers 3

You can use a notificationlistenerservice to get an active notification. This returns a list of StatusBarNotifications, then just:

StatusBarNotifcation sBNotification = activeNotifications[0]; Notification notification = sBNotification.getNotification(); int argbColor = notification.color; 

Answers 4

If you change ImageButton to ImageView in your layout you can update it with

    RemoteViews remoteView = getRemoteViews(context);       // load base icon from res     Bitmap baseIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.base_icon);      // edit Bitmap baseIcon any way for your choose     Bitmap editedBitmap = ...     // update notification view with edited Bitmap     remoteView.setImageViewBitmap(R.id.button_icon, edited); 

P.S. you can edit Bitmap like this: https://stackoverflow.com/a/5935686/7630175 or any other way

Hope it's help

Answers 5

for background can you try these attributes...

app:backgroundTint="@color/pay" 

---------Or-------------

android:tint="@color/white" 
Read More

Wednesday, July 5, 2017

How to create signals on insert, delete or update commands in PostgresSQL and handle them in C++?

Leave a Comment

I'm trying to find the best way to get notified by the database when there are insert, delete or update commands in PostgresSQL.

My goal is to handle changes in the database as soon as they happen.

How can I do that?

3 Answers

Answers 1

I've found a good way of doing that in Qt.

First, you need to create rules to notify you that updates had happened:

CREATE RULE table_notification_insert AS ON INSERT TO public.table DO NOTIFY table_inserted; CREATE RULE table_notification_update AS ON UPDATE TO public.table DO NOTIFY table_updated; CREATE RULE table_notification_delete AS ON DELETE TO public.table DO NOTIFY table_deleted; 

Then, you can use Qt to receive each notification ("table_inserted", "table_updated", "table_deleted") as follows:

QSqlDatabase::database().driver()->subscribeToNotification("table_inserted"); QObject::connect(QSqlDatabase::database().driver(), SIGNAL(notification(const QString&)), /*handlerObjectPointer*/, SLOT(handleNotificationFunction(const QString&))); 

Here is where I found part of the answer: forum.qt.io

Answers 2

The following book might help you especially page 392 : https://books.google.ca/books?id=gkQVL9pyFVYC&pg=PA379&lpg=PA379&dq=signal+postgresql+c%2B%2B&source=bl&ots=E7AhQWKBrW&sig=N-lj9prsYMe7eTEou9A84ITKSbI&hl=en&sa=X&ved=0ahUKEwi_sJO1tPLUAhWEWD4KHY1JCI4Q6AEINDAD#v=onepage&q=signal%20postgresql%20c%2B%2B&f=false

Answers 3

CREATE RULE table_notification_insert AS ON INSERT TO public.table DO NOTIFY table_inserted; CREATE RULE table_notification_update AS ON UPDATE TO public.table DO NOTIFY table_updated; CREATE RULE table_notification_delete AS ON DELETE TO public.table DO NOTIFY table_deleted; 

https://javacodepoint.com

Read More

Thursday, April 27, 2017

Possible to overwrite existing push notification on iOS

Leave a Comment

In Android it is possible to overwrite an existing push notification if you keep using the same notification id.

Is the same possible for iOS in any way?

It seems hard to find any information about replacing an push notification, because a lot of answers are using silent push notifications and remove them manually.

I use Cordova so I have limited options for background processes when receiving push notifications.

On iOS I cannot run code to manually remove any push notifications when the app is in the background.

1 Answers

Answers 1

No, in iOS you can not overwrite already scheduled remote / local notification.

You have to schedule another push notification.

By maintaining some flag or checking on key / value. You have to remove previous notification while reviving new notification.

Hope this helps.

Updated

As an alternate, once you receive push notification, on based of information you received in push notification payload.

You can schedule local notification.

import UIKit import PushKit  @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate,PKPushRegistryDelegate {  var window: UIWindow? let notificationObject = UILocalNotification()  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {       return true }  func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {        notificationObject.fireDate = NSDate(timeIntervalSinceNow: 1)     notificationObject.alertBody =  "Title"     notificationObject.alertAction = "Open"     notificationObject.soundName = "SoundFile.mp3"     notificationObject.category = ""     notificationObject.userInfo = "As per payload you receive"      UIApplication.sharedApplication().scheduleLocalNotification(notificationObjectCall)   } 

As you can see in above code, local notification object is declared globally. So that object will get overwrite again and again whenever you receive payload.

For remote notification, you can not make object and overwrite it.

I am not much aware of cordova, but in native iOS, this way, you can do overwrite using local notification.

Hope you understand what technique is been used and help you figure out solution.

Read More

Wednesday, April 19, 2017

Notification Sound, Vibration and LED don't work

Leave a Comment

I'm trying to set custom Sound, Vibration and LED colors for the Notificaitons in my app - but it doesn't work. Everything else like setting the title, icon, color etc work fine. I've tried many solutions suggested in Stackoverflow but they didn't work either, so I'm asking a question.

Here is my notification code -

    Intent resultIntent = new Intent(this, ActivityB.class);     Bundle b = new Bundle();     //Some bundle related Code     resultIntent.putExtra("bundle",b);      TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);     stackBuilder.addNextIntent(new Intent(this, ActivityA.class));     stackBuilder.addNextIntent(resultIntent);      PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);      android.support.v7.app.NotificationCompat.Builder builder = new android.support.v7.app.NotificationCompat.Builder(this);     builder.setSmallIcon(R.drawable.ic_small_logo);     builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_logo_large));     builder.setContentTitle(notification.getTitle());     builder.setContentText(notification.getBody());     builder.setColor(Color.parseColor("#FFFFFF"));     builder.setStyle(new NotificationCompat.BigTextStyle());     builder.setVibrate(new long[] { 1000, 100, 1000, 100, 1000 });     builder.setLights(Color.YELLOW, 3000, 3000);     builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notif1));     builder.setAutoCancel(true);     builder.setContentIntent(resultPendingIntent);      NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);     notificationManager.notify(1, builder.build()); 

I have added permission for Vibration too. Tested this on 2 phones running Lollipop and Marshmallow.

Edit 1:

Sharing all the permissions that my application uses -

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.android.alarm.permission.SET_ALARM" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.VIBRATE"/> 

Edit 2: Works on Marshmallow version phone. Does not work on Phones with Lollipop.

Edit 3: Works on Nougat too (One plus 3T Phone).

3 Answers

Answers 1

Based on your comments, it seems to be problem with your phone itself. I was asking in (1) regarding the vibration because you are setting { 1000, 100, 1000, 100, 1000 } which is a 1000 ms delay, followed by 100 ms vibration. This can be too little to detect.

Anyway, I had the same problem for vibration on some devices, so I used vibrator service directly instead. What I did was like this after issuing the notification. As per you comment below, I also added the ringtone manager section.

// built the notification without vibration and sound NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(1, builder.build()); // start vibrator manually Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); vibrator.vibrate(new long[] {1000, 100, 1000, 100, 1000}, Constants.VIBRATION_ONCE); // start sound manually Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notif1); Ringtone ringtone = RingtoneManager.getRingtone(this, uri); ringtone.play(); 

This seems to work for most devices. As for the light of the notification, it is already stated in Official Document that

Set the desired color for the indicator LED on the device, as well as the blink duty cycle (specified in milliseconds). Not all devices will honor all (or even any) of these values.

If you are using Mi devices, try to "trust" the app and enable all permissions required for notifications, including "auto-start". It will work in most cases.

Answers 2

One of the reasons the sound does not work is because it cannot find the file change from builder.setSound(Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.notif1)); to

String uriSound = String.format("android.resource://%s/raw/%s",getPackageName(), R.raw.notif1);

   builder.setSound(uriSound); 

For the lights use RGB combinations. builder.setLights(Color.rgb(130, 130, 130));

change the vibration pattern to something more uniform,

builder.setVibrate(new long[] { 50, 100, 150, 200, 250}); 

Answers 3

Try this one may be this help you out.

For Lights...

notification.ledARGB = 0xff00ff00; notification.ledOnMS = 300; notification.ledOffMS = 1000; notification.flags |= Notification.FLAG_SHOW_LIGHTS; 

For Vibration...

long[] vibrate = {0,100,200,300}; notification.vibrate = vibrate; 

Reference link 1

Read More

Wednesday, February 8, 2017

how to send fcm notification to multiple device in single fcm reqest

Leave a Comment

i want to send notification to multiple device in single fcm request. my notification text is same for all devices.i have to send more then 10000 notification at same time to all user and text is same so i want to send all notification in minimum fcm request. I am using c# asmx service. hear is my code.

string regid="fcm_reg_id1,fcm_reg_id2" like this.

string applicationID = "abcd";

string SENDER_ID = "123456";

            string regid="c_Z5yRoj4TY:APA91bGry2g_CIA1xaRy_LscxOvFX6YHqasKA96TjpG6yi1yytNyM5rtGL6DgxjGMSE5c74d7VdSL6W8zxO1ixVMlpVMwdgcrsGUWV0VfdbddC2XD","c_Z5yRoj4TY:APA91bGry2g_CIA1xaRy_LscxOvFX6YHqasKA96TjpG6yi1yytNyM5rtGL6DgxjGMSE5c74d7";              HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("https://fcm.googleapis.com/fcm/send");              httpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";              httpWebRequest.Method = "POST";              String collaps_key = "Score_update";              string json = "collapse_key=abcd" + "&data.header=cricket&registration_id=" + regId + "&data.notificationId=" + notificationId + "&data.message=" + msg;              httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", applicationID));             httpWebRequest.Headers.Add(string.Format("Sender: key={0}", SENDER_ID));              using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))             {                 //Console.WriteLine(json);                 streamWriter.Write(json);                 streamWriter.Flush();                 streamWriter.Close();                 using (HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse())                 {                     using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))                     {                         var result = streamReader.ReadToEnd();                         Console.WriteLine(result);                         retmsgid = result.ToString();                         if (retmsgid.Trim() != "")                         {                             ResponceString = result.ToString();                             string[] msgsplits = retmsgid.Split(',');                             string[] msg1 = msgsplits[0].ToString().Split(':');                             ReturnMessageId = msg1[1].ToString();                         }                         else                         {                             ReturnMessageId = "0";                         }                     }                     httpResponse.Close();                     httpResponse.Dispose();                     httpWebRequest = null;                 }             }  

1 Answers

Answers 1

Since FCM does not allow specifying more than 1000 registration IDs when sending a message:

This parameter specifies a list of devices (registration tokens, or IDs) receiving a multicast message. It must contain at least 1 and at most 1000 registration tokens.

You only option is sending a message to a topic

Read More

Friday, June 17, 2016

iOS: Local notification very slow to show up when phone locked

1 comment

We've been developing an iOS application (iOS 9+ only) in Swift. We are using VOIP notifications for certain things then use local notifications to actually show the message to the user.

My problem is that when the phone is locked it can take up to 15 seconds for the local notification to actually get displayed, even though I can see my debug output and the code being ran immediately when I expect it.

This is my code for showing the notification:

let notification = UILocalNotification()     notification.alertTitle = "Title text.".local     notification.alertBody = "Body text."     notification.alertAction = "Action".local     notification.category = Notification.CallCategory     notification.soundName = localNotificationSoundName     notification.userInfo = msg.dictionary()      UIApplication.sharedApplication().presentLocalNotificationNow(notification) 

Other than the delay everything works as expected and when the phone is not locked there is no delay and the notification works as expected.

Any ideas?

EDIT

As a clarification this code is being run inside a switch/case that resides in our implementation of PKPushRegistryDelegate. Specifically within this function:

func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) 

Additionally it is worth noting that this not happen on every device. We have one iPhone 6s test device where it happens every time, regardless of how many times we reboot the device, reinstall the app or even upgrade iOS to a newer version. We have a few other test devices where it doesnt happen.

1 Answers

Answers 1

Read this from Apple doc -

Prioritize Remote Notification Delivery

Remote notifications provided by your server to the Apple Notification Service include a variety of elements, including payload data, an expiration date, a priority, and more. Remote notifications support two levels of push priority. One delivers the notification immediately. The other delays delivery of the notification until an energy-efficient time. Unless a notification truly requires an immediate delivery, use the deferred delivery method.

NotificationBestPractices

  1. I know your problem is for slow local notification but still make sure you have Prioritize remote notification.

  2. I have experienced while testing that app has certain delay when using local notifications. Maybe that is how system is designed and not necessarily a flaw. For VOIP case I still think you should have used push notification to notify the call (Maybe you have some internal calculation before making notification). But do check out Facebook messenger app, it looks like it does mix match push / local notification to notify user for calls. Try to observe the delay if any.

  3. Make another simple app which shows Local Notification for same code as above and observe if it too has some delay. For this test don't use remote notification to fire the Local Notification, just test after app launch or something like that. This is to make sure if system is delaying certain apps notification for case immediately after push notification ?

Read More

Thursday, May 5, 2016

How to enable multiple BLE characteristic notifications on Xamarin/Android?

Leave a Comment

I am trying to enable notifications for more than one BLE characteristic using Xamarin/Android but seem unable to do so. The app seems to stop receiving any BLE events if I try and enable more than one at a time.

Can anyone confirm whether this is possible using Tamarin/Android. We have a native iOS app that works just fine with multiple notifications enabled. The basic steps we use are as follows:

  1. Scan for device
  2. Connect to device
  3. Discover services
  4. For each discovered service iterate through characteristics and enable the ones that are required
  5. Process each asynchronous callback event in the BLE callback

Any time we try and enable notifications on more than one characteristic we no longer receive any events.

I have also been unable to find any examples where more than one characteristic is being enabled.

I hope I have simply missed something fundamental about using the Xamarin/Android APIs here.

public override void OnServicesDiscovered (BluetoothGatt gatt, GattStatus status) {     base.OnServicesDiscovered (gatt, status);     foreach (BluetoothGattService service in gatt.Services) {         string uuid = service.Uuid.ToString ().ToUpper();         if (uuid.Equals (BLEServices.HRService.ToUpper())) {             _Adap.LogMessage ("HRService discovered");             foreach(BluetoothGattCharacteristic characteristic in service.Characteristics) {                 string c_uuid = characteristic.Uuid.ToString ().ToUpper ();                 _Adap.LogMessage (" HRCharacteristic: " + c_uuid);                  if (c_uuid.Equals(_Adap.useCharacteristic.ToUpper())) {                     _Adap.LogMessage ("  enabling HRCharacteristic");                     gatt.SetCharacteristicNotification(characteristic, true);                     BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);                     characteristic.AddDescriptor (descriptor);                     descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());                     gatt.WriteDescriptor (descriptor);                     _Adap.StartTimer ();                 }             }          } else if (uuid.Equals (BLEServices.BatteryService.ToUpper())) {             _Adap.LogMessage ("BatteryService discovered");             foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {                 string c_uuid = characteristic.Uuid.ToString ().ToUpper ();                 _Adap.LogMessage (" BatteryService: " + c_uuid);                  if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ())) {                     _Adap.LogMessage ("  reading batteryCharacteristic");                     // This may only be reported when the battery level changes so get the level first by doing a read                     gatt.ReadCharacteristic (characteristic);                      //gatt.SetCharacteristicNotification (characteristic, true);                     //BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);                     //characteristic.AddDescriptor (descriptor);                     //descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());                     //gatt.WriteDescriptor (descriptor);                 }             }         } else if (uuid.Equals (BLEServices.DeviceInfoService.ToUpper())) {             _Adap.LogMessage ("DeviceInfoService discovered");             foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {                 string c_uuid = characteristic.Uuid.ToString ().ToUpper ();                 _Adap.LogMessage (" DeviceInfoService: " + c_uuid);                 if (c_uuid.Equals (BLEServices.kModelNumberCharacteristicUuidString.ToUpper ())) {                     //gatt.ReadCharacteristic (characteristic);                 }             }         } else if (uuid.Equals (BLEServices.kHxM2CustomServiceUuidString.ToUpper())) {             _Adap.LogMessage ("HxM2CustomService discovered");             foreach (BluetoothGattCharacteristic characteristic in service.Characteristics) {                 string c_uuid = characteristic.Uuid.ToString ().ToUpper ();                 _Adap.LogMessage (" HxM2CustomCharacteristic: " + c_uuid);                  if (c_uuid.Equals (_Adap.useCharacteristic.ToUpper ())) {                     _Adap.LogMessage ("  enabling HxM2 characteristic: "+_Adap.useCharacteristic);                     gatt.SetCharacteristicNotification (characteristic, true);                     BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read);                     characteristic.AddDescriptor (descriptor);                     descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ());                     gatt.WriteDescriptor (descriptor);                     // Start a timer to make sure that we can recover if we never receive any data from the device                     _Adap.StartTimer ();                 }              }         } else {             _Adap.LogMessage ("Unknown Service "+uuid+" discovered");         }     } } 

Can anyone explain what the following lines are for

BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor (Java.Util.UUID.FromString (BLEServices.CLIENT_CHARACTERISTIC_CONFIG), GattDescriptorPermission.Write | GattDescriptorPermission.Read); characteristic.AddDescriptor (descriptor); descriptor.SetValue (BluetoothGattDescriptor.EnableNotificationValue.ToArray ()); gatt.WriteDescriptor (descriptor); 

1 Answers

Answers 1

Beside your found solution: Be aware, that you can't listen to an unlimited number of characteristics. The maximum is limited hardcoded in the android source to BTA_GATTC_NOTIF_REG_MAX.

So your app should not rely on more than the maximum number of notifying characteristics of your minimum supported android version.

Read More