【问题标题】:How to display a notification when my application is in background?当我的应用程序在后台时如何显示通知?
【发布时间】:2018-06-26 11:27:16
【问题描述】:

​我正在尝试构建一个具有 -

的 Android 应用程序

一个第一个活动(启动器活动)

还有一个第二个活动

我想要达到的目标:

First Activity 从用户获取输入,使用 AsyncTaskLoader 从 Web 获取数据。 在 onLoadFinished 中,它会检查输入是否有效,以及是否启动 Intent to Second Activity 以显示更多详细信息。输入也与 Intent 一起传递。

由于网络操作可能需要时间,所以我决定在创建第二个活动之前使用 IntentService 显示通知,即在 onLoadFinished 之前调用通知意图。如果第二个 Activity 尚未启动,则通知应直接启动它。

什么工作正常:

活动和加载程序都工作正常。通知也会显示,只要用户保持应用运行,一切都会按预期工作。

什么不是:

当用户在加载数据时离开第一个活动时,通知不会显示,因为 onPause 已执行。我尝试搜索它并了解了 BroadcastReceiver、JobScheduler 和 FirebaseJobDispatcher,但我无法真正理解它们以及它们如何提供帮助。

那么,我走对了吗?即使应用程序进入后台,我怎样才能实现相同的功能?

附:代码比问题建议的要大得多,所以我没有包括它。这就是为什么如果解释看起来不完整或混乱,我会尽力澄清你的疑问。

【问题讨论】:

    标签: java android notifications background broadcastreceiver


    【解决方案1】:

    通过 LocalBroadcastManager 注册一个广播接收器,并定义过滤器。现在,根据过滤器,您可以使用 UI 元素或意图。

    IntentFilter filter = new IntentFilter();
        filter.addAction("A");
        filter.addAction("B");
        filter.addAction("C");
        LocalBroadcastManager.getInstance(getContext()).registerReceiver(dummyReceiver, filter);
    
    
    
    private BroadcastReceiver dummyReceiver = new BroadcastReceiver() {
    @Override
        public void onReceive(final Context context, final Intent intent) {
              //Do your work**
     }}
    

    试试这个。我已经实现了它并且它有效。

    【讨论】:

    • 赞成。但是如果我在 AsyncTaskLoader 的 onLoadFinished 中注册它,当活动在后台时它不会被执行,我需要根据返回的数据验证输入。那么我应该在哪里注册接收者?
    • 如果你有一些按钮点击或一些动作要采取,所以在动作上注册接收者并执行你的异步任务和其中的一切。
    【解决方案2】:

    是的。你走在正确的轨道上。

    这是我制作的地图下载器的示例。我希望你不介意,但由于你没有给出上下文,我必须找到一个合适的例子。

    /**
    * @param entry the map entry to be downloaded
    * @return returns a receiver that unzips the map file after downloading
    */
    private BroadcastReceiver createMapReceiver(MapEntry entry) {
         return new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 unregisterReceiver(this); // we unregister this receiver after the download is complete
                 receiveDownloadedFile(entry); // once we receive the map file, we run this function, but you can do whatever you want. This is the part of the code youn were asking for
             }
         };
    }
    
    
    void downloadMap() {
    
        // preparing the download
        BroadcastReceiver receiver = createMapReceiver(entry); // see function above
    
      DownloadManager manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
      registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    
      String downloadURL = fileListURL + entry.getFileName() + fileExtension; // building the url for the map
      DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadURL));
    
      if (manager != null) {
          manager.enqueue(request
                  .setDestinationUri(Uri.fromFile(new File(areaFolder, entry.getFolderName())))
                        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI|DownloadManager.Request.NETWORK_MOBILE)
                        .setAllowedOverRoaming(false)
                        .setTitle("Some title, preferably taken from Strings.xml")
                        .setDescription("Some Description")
                        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
                );
            } else {
                // if we couldn't find the DownloadManager
                onFailure(entry); // we simply run some onFailure function
            }
    
        }
    

    不要忘记权限。

    【讨论】:

    • 赞成。但是如果我在 AsyncTaskLoader 的 onLoadFinished 中注册它,当活动在后台时它不会被执行,我需要根据返回的数据验证输入。那么我应该在哪里注册接收者?
    • 如果您需要做的事情太复杂,您应该将所有这些行为封装在一个服务中。服务就是这样:即使应用程序被隐藏,代码也会在后台运行。看看文档。如果您在那之后仍然需要帮助。我很乐意为您提供帮助。
    【解决方案3】:

    即使应用程序进入后台,我怎样才能实现相同的功能

    使用bound services 或intent services。 意图服务允许您异步执行操作。 绑定服务可以使用aidl提供接口。只要服务被绑定,它就不太可能被破坏。有多种方法可以使用标志绑定服务。

    恕我直言,activity 只是一种显示 UI 的方式。如果您需要任何后台工作,请使用服务。 通过aidl 使用绑定服务时,您必须扩展service connection。绑定后会从service接收接口。

    【讨论】:

      【解决方案4】:

      我终于在不使用 BroadcastReciever 或 Service 的情况下使其工作,因此不熟悉它们的人可以从中参考,但 自行决定使用它 因为 Services 和 Recivers 是推荐的方式。

      @Override
      public void deliverResult(Data data) {
          super.deliverResult(data);
          showNotification(input);
      }
      

      这是AsyncTaskLoader中获取数据后触发的方法。覆盖它并更改响应通知点击的通知方法。

      private PendingIntent onClick(Context context) {
           return PendingIntent.getActivity(context, 0, new Intent(context, ExtraActivity.class).
      putExtra(Intent.EXTRA_TEXT,input),PendingIntent.FLAG_UPDATE_CURRENT);
      }
      

      ExtraActivity 类似于 this 。即使活动已关闭但通知尚未关闭,它也允许您的通知做出响应。

      同样,这只是针对这种特定情况的一种解决方法,它导致我在许多地方传递输入变量,因此它在性能方面可能不如其他选项高效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-08
        • 2019-09-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多