Coder超
Coder超
  • 发布:2020-03-26 15:15
  • 更新:2024-02-18 11:03
  • 阅读:11964

分享uniapp使用原生Android推送消息(内推)以及点击通知监听数据

分类:uni-app

前言

由于用uniapp官方的plus.push.createMessage()在Android平台下推送通知无法显示推送时间,需要调用原生Android推送通知。
在社区综合了各大神的代码,具体如下:

推送

推送事件:

/**  
  * android原生通知发送  
  * @param content 通知内容  
  * @param data json对象,存储通知的隐藏数据,用于点击通知时接收使用  
  */  
 android_notify(content = '', data = {}) {  
  // #ifdef APP-PLUS  
  var title = '通知标题';  

  console.log('准备通知');  
  console.log(plus.os.name);  

  //Android平台下才使用此推送  
  if (plus.os.name != 'Android') {  
   return false;  
  }  

  //随机生成通知ID  
  var NotifyID = Math.floor(Math.random() * 10000) + 1;  

  var main = plus.android.runtimeMainActivity();  
  var Context = plus.android.importClass("android.content.Context");  
  var NotificationManager = plus.android.importClass("android.app.NotificationManager");    
  var nm = main.getSystemService(Context.NOTIFICATION_SERVICE);  

  var Notification = plus.android.importClass("android.app.Notification");  
  var Intent = plus.android.importClass("android.content.Intent");  
  var PendingIntent = plus.android.importClass("android.app.PendingIntent");  
  var intent = new Intent(main, main.getClass());  

  //传递参数  
  var payload = {  
   'msg':content,  
   'notify_id':NotifyID,  
   'data':data  
  };  
  intent.putExtra("receive", JSON.stringify(payload));  

  //PendingIntent.getActivity的第二个参数需要设置为随机数,否则多个通知时会导致前面的通知被后面的通知替换Extra的数据  
  var pendingIntent = PendingIntent.getActivity(main, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);  
  var SystemVersion = plus.os.version;  
  var firstVersionNumber = Number(SystemVersion.split('.')[0]);  
  var r = plus.android.importClass("android.R");  
  var mNotification;  

  //判断当前系统版本在8.0及以上  
  if (firstVersionNumber >= 8){  
   var NotificationChannel = plus.android.importClass('android.app.NotificationChannel');  
   var channel = new NotificationChannel("s"+ NotifyID, "1", NotificationManager.IMPORTANCE_HIGH);  
   nm.createNotificationChannel(channel);  
   Notification = plus.android.importClass("android.support.v4.app.NotificationCompat");  
   mNotification = new Notification.Builder(main, "s" + NotifyID);  
  } else {  
   Notification = plus.android.importClass("android.app.Notification");  
   mNotification = new Notification.Builder(main);      
  }  

  mNotification.setContentTitle(title)       //设置标题  
  mNotification.setContentText(content);       //设置内容  
  //mNotification.setSubText('');        //子内容暂时去掉  
  mNotification.setAutoCancel(true);       //设置点击消失  
  mNotification.setShowWhen(true);       //显示通知时间,貌似不加这句也能显示  
  mNotification.setTicker("PadInfo");       //弹出通知  
  mNotification.setSmallIcon(17301620);       //设置当前app图标  
  //mNotification.setDefaults(Notification.DEFAULT_VIBRATE);  //声音、闪灯、震动效果,可叠加,此语句无效  
  mNotification.setPriority(Notification.PRIORITY_DEFAULT);   //通知优先级    
  mNotification.flags=Notification.FLAG_ONLY_ALERT_ONCE;     //发起通知时震动    
  mNotification.setContentIntent(pendingIntent);    
  var mNb = mNotification.build();  

  //判断当前系统版本在8.0及以上    
  if (firstVersionNumber >= 8){  
   nm.notify("s" + NotifyID, NotifyID, mNb);    
  } else {  
   nm.notify(NotifyID, mNb);  
  }  
  //void plus.device.beep(2);//bee bee叫  
  plus.device.vibrate(300);//震动  

  console.log('通知结束');  
  return true;  
  // #endif  
 }  

调用方法:

android_notify('test', {  
    params1: 'params1',  
    params2: 'params2',  
    params3: 'params3',  
    params4: 'params4'  
});

接收

点击通知接收通知数据

 /**  
  * android原生通知接收  
  */  
 android_receive() {  
  // #ifdef APP-PLUS  
  if (plus.os.name != 'Android') {  
   return false;  
  }  
  //android原生通知栏接收器(程序退出后无效)  
  var main = plus.android.runtimeMainActivity();  
  var intent = main.getIntent();  
  var message = intent && intent.getExtra != undefined ? intent.getExtra("receive") : null;  
  console.log(message);  
  message = message ? JSON.parse(message) : '';  
  if (message) {  
   //删除当前通知  
   // var Context = plus.android.importClass("android.content.Context");  
   // var nm = main.getSystemService(Context.NOTIFICATION_SERVICE);  
   // console.log(message.notify_id);  
   //nm.cancel('s' + message.notify_id, message.notify_id);//安卓版本大于等于8的  
   //nm.cancel(message.notify_id);//安卓版本小于8的  
   // nm.cancelAll();  

   //把消息数据置空,以免再次打开APP时重复执行此处  
   intent.putExtra("receive", '');  

   var params = message.data;  
   if (params1 == 'xxx') {  
    //TODO do something.  
   } else if (params1 == 'yyy') {  
    //TODO do something.  
   }  
  }  
  // #endif  
 }  

调用方法

  // App.Vue  
  onShow: function() {  
   ...  

   // #ifdef APP-PLUS  
   android_receive();  
   // #endif  

   ...  
  },

注意事项

  1. 已知问题:第一次通知会有通知延迟现象,大概2-3秒后才会收到通知,之后就不会了(官方的推送没有此问题);
  2. 程序被关闭后点击通知消息无法再接收到通知的数据(暂时没有好的解决方案,如果大家有好的方法,欢迎回复分享);

希望能帮助大家。


  • 2020年4月3日补充:

  • 多行显示通知消息

//创建大文本样式  
var bigTextStyle = plus.android.importClass("android.support.v4.app.NotificationCompat$BigTextStyle");  
var style = new bigTextStyle();  
style.setBigContentTitle(title);  
// style.setSummaryText("备注一行");  
style.bigText(content);//这里可以设置超长的文本  
mNotification.setStyle(style); //设置大文本样式

以上代码放到var mNb = mNotification.build();之前即可

3 关注 分享
aliang888 linnian CV工程师小刘

要回复文章请先登录注册

9***@qq.com

9***@qq.com

回复 1***@qq.com :
通知图标你怎么自定义的
2024-02-18 11:03
轻飏

轻飏

您好,我想问问setSmallIcon 这个方法,怎么使用自定义的图片呢
2023-05-15 10:16
1***@qq.com

1***@qq.com

系统消息栏有提示,但是没有弹窗显示,大佬们这咋办?
2022-10-23 14:50
安卓无障碍开发

安卓无障碍开发

android.support.v4.app.NotificationCompat要改成androidx.core.app.NotificationCompat
2022-06-10 16:32
1***@qq.com

1***@qq.com

回复 l***@163.com :
是因为 Notification = plus.android.importClass("android.support.v4.app.NotificationCompat"); 导包导错了
改为这个可以正常运行Notification = plus.android.importClass("android.app.Notification");
2022-04-27 16:18
l***@163.com

l***@163.com

这个在自定义基座上测试是没有问题,但是安卓离线打包是有问题的,mNotification = new Notification.Builder(main, 's' + NotifyID) 代码往下就不执行了 打印main也打印不出来,在自定义基座上打印出来是一个对象
2021-06-15 14:13
1***@qq.com

1***@qq.com

这篇文章实实在在的解决了我希望用原生实现通知的一些问题,非常感谢大佬的分享

我这里也有几点内容添加,希望有解决到某些问题,有不对的地方也烦请指出
1、 //PendingIntent.getActivity的第二个参数需要设置为随机数,否则多个通知时会导致前面的通知被后面的通知替换Extra的数据
var pendingIntent = PendingIntent.getActivity(main, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
改为
var pendingIntent = PendingIntent.getActivity(main, NotifyID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent.getActivity这个方法中的参数第二位在安卓开发官方的介绍中是这样描述的 “requestCode Int:发送者的私人请求代码” 我之前有看到它介绍并不重要(我也不记得在哪看到的了),但是这个参数在每条通知中都不同的话是可以解决上文中提到的第二点问题 “程序被关闭后点击通知消息无法再接收到通知的数据”
附安卓开发文档链接:https://developer.android.google.cn/reference/kotlin/android/app/PendingIntent#getactivity_1

2、上述方法中,在安卓8.0以上NotificationChannel的参数(id: String!, name: CharSequence!, importance: Int)第一个参数是通道的ID,这个通道是在原生UI设置中可以看到的,这个通道在通知结束后UI是不会删除的,如果一直创建新的会把通知设置中的通知类别一栏拉的很长,所以某一类通知用一个通道就好,我这边解决的方案是在8.0以上创建通道时给个参数并加以判断,存在不创建,不存在则创建。
附安卓开发文档链接:https://developer.android.google.cn/reference/kotlin/android/app/NotificationChannel
2020-12-29 10:52
linnian

linnian

回复 linnian :
附赠安卓文档地址,发现果然被弃用了
This constructor was deprecated in API level 26.1.0. use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.
https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html
2020-09-15 17:13
linnian

linnian

#### 非常感谢您的分享,解决了问题
正在发愁官方native示例中的通知不管用,查看原生实现,也是同样的方式。看您的代码,才知道原来最新安卓版本的api已经有了更改。
2020-09-15 17:09
cnbany

cnbany

android_receive 取不到 message

测试发现:
[Vue warn]: Error in onShow hook: "TypeError: intent.getExtra is not a function. (In 'intent.getExtra("receive")', 'intent.getExtra' is undefined)"

这是什么原因?
2020-07-03 23:47