如何在service中同步更新通知activity中的进度条

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在service中同步更新通知activity中的进度条相关的知识,希望对你有一定的参考价值。

目前做一个下载功能,需要在service中同步更新notification中的进度条和某一个activity中的进度条,notification中显示所有下载项的下载进度,单击某一下载进度条,启动本下载项目的详细下载界面,包含当前下载项的下载进度条和下载控制按钮(暂停,删除等)问题:如何在service中实现notification 和 activity中进度条的同步更新?(注:不用广播)

方法1、使用Handler在Service发送进度消息 2、activity中实现一个回调的接口,然后注册到服务里 3、用广播 参考技术A 在activity中new一个handler,将handler传给service和notification,在service中通过向handler中发消息,然后在activity和notification的handler中处理更新信息.只是猜想,具体没做过,不知道能不能达到目的,希望能对你的问题有所帮助. 参考技术B 也遇到了这样的问题,感觉还是使用广播的多些吧!

Android - 收到推送通知 FCM 后,如何在我的 Activity 中更新数据或 UI?

【中文标题】Android - 收到推送通知 FCM 后,如何在我的 Activity 中更新数据或 UI?【英文标题】:Android - How can I update data or UI in my Activity when Push Notification FCM is received? 【发布时间】:2020-02-11 08:22:09 【问题描述】:

我有以下FirebaseMessagingService,当我收到推送通知并且应用程序处于前台时,它可以正常工作:

public class _FCMService extends FirebaseMessagingService 
   @Override
   public void onMessageReceived(RemoteMessage remoteMessage) 
      if (remoteMessage.getData().size() > 0) 
         // Log.i(TAG, "PUSH PAYLOAD: " + remoteMessage.getData());

         JSONObject pushData = new JSONObject(remoteMessage.getData());
         pushType = pushData.optString("pushType");
         pushMessage = pushData.optString("body");
         Log.i(TAG, "ON PUSH RECEIVED - pushType: " + pushType);
         Log.i(TAG, "ON PUSH RECEIVED - pushMessage: " + pushMessage);


         Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
         NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                 .setContentText(pushMessage)
                 .setStyle(new NotificationCompat.BigTextStyle())
                 .setAutoCancel(true)
                 .setSmallIcon(R.mipmap.ic_launcher)
                 .setSound(defaultSoundUri);
         NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
         assert notificationManager != null;
         notificationManager.notify(0 , notificationBuilder.build());
      
   



   @Override
   public void onNewToken(@NotNull String token) 
      Log.i(TAG, "Refreshed token: " + token);
      ANDROID_DEVICE_TOKEN = token;
   

所以,如果我收到推送,Logcat 会打印出通知正文和(如果存在)pushType 字符串。

我需要做的是在收到推送时让我的其他活动更新数据,以及获取pushMessagepushType 字符串。

我知道如何在 iOS Swift 中做到这一点 - 使用 NotificationCenter - 但不知道 Android,我尝试过 LocalBroadcaster,但没有成功。

【问题讨论】:

【参考方案1】:

LocalBroadcastManager 现已弃用!

您可以在静态引用中使用LiveData 实现并在ActivityFragment 中观察它

public class NotificationService extends FirebaseMessagingService 

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) 
        super.onMessageReceived(remoteMessage);
        
        Notification.
                    getInstance().
                    addOrder(remoteMessage.getData().get("id"));
        
    

    public static class Notification 
        private static Notification instance;
        private MutableLiveData<String> newOrder;

        private Notification() 
            newOrder = new MutableLiveData<>();
        

        public static Notification getInstance() 
            if(instance == null)
                instance = new Notification();
            
            return instance;
        

        public LiveData<String> getNewOrder() 
            return newOrder;
        

        public void addOrder(String orderID)
            newOrder.postValue(orderID);
        
    

而在ActivityFragment

NotificationService.
   Notification.
       getInstance().
       getNewOrder().
       observe(getViewLifecycleOwner(), new Observer<String>() 
           @Override
           public void onChanged(String s) 
               //TODO: update your ui here...
           
       );

【讨论】:

【参考方案2】:

您可以将.setContentIntent(NotificationChannelUtil.createPendingIntent(this, pushMessage, pushType)) 添加到您的通知构建器。

该函数在 util 类中的位置,例如:

public class NotificationChannelUtil 

    private NotificationChannelUtil() 

 public static PendingIntent createPendingIntent(Context context, String pushMessage, String pushType) 
        Intent intent = new Intent(context, YourWantedActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.putExtra("pushMessage", pushMessage);
        intent.putExtra("pushType", pushType);
        return PendingIntent.getActivity(context, 0 /* request code */, intent,
                PendingIntent.FLAG_ONE_SHOT);
    

【讨论】:

谢谢,但是如何在我的活动中调用它?我的意思是,例如,我如何获取 pushMessage 字符串和 Logcat 它? 意图意图 = getIntent(); String pushMessage = intent.getStringExtra("pushMessage"); String pushType = intent.getStringExtra("pushType"); 谢谢,但是当我收到推送后,当我进入我的活动时,它给了我“null”。这是场景:我在一个聊天活动中,它是打开的,我正在与之交互,然后我收到一个推送通知,我需要自动让我的活动来获取它并调用一个函数来刷新数据,你知道吗我是说?也许我需要一个观察者,类似的东西,不断监听推送事件 当您单击通知时,此待处理通知有效!不管它是在前台还是后台。如果你想被自动重定向到你的 Activity,你应该考虑创建一个类似的简单 Intent 并使用相同的“putExtra”并在“onMessagedReceived”中调用它 - 但你应该测试它是否在后台和前台工作正常。 (如果没有,仅当应用程序在前台时才制作简单的 Intent,否则使用 PendingIntent 的方式) "当您单击通知时,此待处理通知有效!" -> 好的,我知道,所以这不是我的问题,我需要在我的活动打开时获取推送数据。在 iOS 中,您可以使用 NotificationCenter 观察者,它会持续监听诸如推送之类的事件。有没有办法在 Android 上也能做到这一点?【参考方案3】:

我找到了解决我的问题的方法,它实际上看起来类似于 iOS NotificationCenter 实例。我已将此类添加到我的 _FCMService.java 文件中:

class NotificationCenter 
   private static NotificationCenter _instance;
   private HashMap<String, ArrayList<Runnable>> registredObjects;
   private NotificationCenter()
      registredObjects = new HashMap<>();
   

   //returning the reference
   static synchronized NotificationCenter defaultCenter()
      if(_instance == null)
         _instance = new NotificationCenter();
      return _instance;
   

   synchronized void addFunctionForNotification(String notificationName, Runnable r)
      ArrayList<Runnable> list = registredObjects.get(notificationName);
      if(list == null) 
         list = new ArrayList<Runnable>();
         registredObjects.put(notificationName, list);
      
      list.add(r);
   

   public synchronized void removeFunctionForNotification(String notificationName, Runnable r)
      ArrayList<Runnable> list = registredObjects.get(notificationName);
      if(list != null) 
         list.remove(r);
      
   

   synchronized void postNotification(String notificationName)
      ArrayList<Runnable> list = registredObjects.get(notificationName);
      if(list != null) 
         for(Runnable r: list)
            r.run();
      
   

然后我在 onMessageReceived() 函数中调用它:

NotificationCenter.defaultCenter().postNotification("pushNotif");

最后,我将观察者添加到我的 Activity 的 onStart() 函数中,如下所示:

@Override
   protected void onStart() 
      super.onStart();

      // Start NotificationCenter to observe for new messages
      NotificationCenter.defaultCenter().addFunctionForNotification("pushNotif", new Runnable() 
         @Override
         public void run() 
            Log.i(TAG, "Obj Details -> pushMessage: " + pushMessage + "\npushType" + pushType);

      );
   

它运行顺利,希望这对其他人有帮助。

【讨论】:

以上是关于如何在service中同步更新通知activity中的进度条的主要内容,如果未能解决你的问题,请参考以下文章

通知在 Activity 中有效,但在 Service 中无效

Android - 收到推送通知 FCM 后,如何在我的 Activity 中更新数据或 UI?

安卓开发:service如何更新Activity里textView的内容。

如何在不同进程中建立Activity和Service之间的双向通信?

在 Android 11 上,如何在不实际点击通知的情况下从通知更新启动 Activity

Service和Activity交互之广播方式