Android 应用程序中逻辑和 GUI 的分离。服务了解应用程序,但不应该

发布于 2024-12-23 11:07:14 字数 1707 浏览 3 评论 0原文

我对 Android 编程来说是一个相对新手(我主要在 Windows 上使用 C#)。我继承了一些由服务和应用程序组成的代码。我想在另一个应用程序中重用该服务和一些应用程序。我把它放在图书馆里。除了一个问题之外,一切都很顺利。该服务有一些代码将主要活动显示在屏幕上。它通过名称呼出此活动。显然,我不能在通用代码中使用它。服务代码看起来像这样:

final int NOTIFY_1 = 0x1001;
NotificationManager notifier = (NotificationManager) context.getSystemService(
                    Context.NOTIFICATION_SERVICE);

final Notification notify = new Notification(
            R.drawable.icon_my_color, ticker, System.currentTimeMillis());

notify.number = 1;
notify.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
 notify.ledARGB = android.graphics.Color.CYAN;
notify.ledOnMS = 500;
notify.ledOffMS = 500;

Intent toLaunch = new Intent(context, MyBankingActivity.class);
toLaunch.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intentBack = PendingIntent.getActivity(context, 0, toLaunch, PendingIntent.FLAG_CANCEL_CURRENT);

notify.setLatestEventInfo(context, title, message, intentBack);
notifier.notify(NOTIFY_1, notify);

当发生一些有趣的事情(银行账户出现负值或其他情况)时,服务将运行此代码。问题是上面硬编码的“MyBankingActivity.class”。我已从库中删除了 MyBankingActivity,因为它是特定于应用程序的。但是,我确实必须让旧应用程序正常运行。我只是希望将其分为库和应用程序,以便我可以在另一个应用程序中重用库中的大量逻辑。在另一个应用程序中,我并不想特别收到此通知 “银行事件”。即使我这样做了,代码目前也是用一个活动的名称进行硬编码的。

这里分离逻辑的正确方法是什么?看起来该服务应该“发布”该事件,感兴趣的应用程序应该“订阅”。至少这是我熟悉的术语。顺便说一句,目前,我刚刚注释掉了整个代码块,并且在旧应用程序中一切正常,当然除了收到此通知之外。

我意识到(并道歉)我的问题很广泛。由于“授人以鱼,不如授人以鱼”可能更好,因此请随意推荐更广泛地涵盖该主题的参考资料/文章/书籍。我尝试自己查看有限的图书馆,但要么我的书太介绍性(《Android in Action》就是其中之一),要么我找错了地方。甚至连建立图书馆和写作服务的话题似乎也很难谈及。在我看来,有几个关键概念是我不擅长的: 1. 服务如何在不了解应用程序的情况下将事件传递给感兴趣的应用程序 2. 如何根据从服务收到的消息将应用程序带到前台 3. 如何获取现有应用程序并进入库(用于非 GUI 或非应用程序特定的内容)和应用程序。 4. 通知如何工作......

提前非常感谢, 戴夫

I'm a relative novice to Android programming (I mostly do C# on Windows). I inherited some code that consists of a service and app. I'd like to reuse the service and some of the app in another app. I'm putting that in a library. All has gone well except for one problem. The Service has some code that puts the main activity up on the screen. It calls out this activity by name. Clearly, I can't have that in common code. The service code looks something like this:

final int NOTIFY_1 = 0x1001;
NotificationManager notifier = (NotificationManager) context.getSystemService(
                    Context.NOTIFICATION_SERVICE);

final Notification notify = new Notification(
            R.drawable.icon_my_color, ticker, System.currentTimeMillis());

notify.number = 1;
notify.flags |= Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
 notify.ledARGB = android.graphics.Color.CYAN;
notify.ledOnMS = 500;
notify.ledOffMS = 500;

Intent toLaunch = new Intent(context, MyBankingActivity.class);
toLaunch.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intentBack = PendingIntent.getActivity(context, 0, toLaunch, PendingIntent.FLAG_CANCEL_CURRENT);

notify.setLatestEventInfo(context, title, message, intentBack);
notifier.notify(NOTIFY_1, notify);

This code gets run by the service when something interesting happens (bank account goes negative or something). The problem is the "MyBankingActivity.class" that is hardcoded above. I have removed MyBankingActivity from the library because it's application specific. However, I do have to have the old app working. I just want it to be separated into a library and app so I can resuse the considerable logic in the library in another app. In that other app, I don't particulary want to be notified of this
"banking event". Even if I did, the code is currently hardcoded with one activity's name.

What is the correct way to separate the logic here? It would seem that the service should be "publishing" the event, and apps that are interested should "subscribe". At least that is the terminology I am familiar with. Incidentally, for now, I have just commented out the entire block of code and everything works fine in the old app, except of course getting this notification.

I realize (and apologize) that my question is broad. As it might be better to "teach a man to fish, rather than give him fish", please feel free to recommend references/articles/books that cover this topic more broadly. I have tried to look at my limited library on my own, but either my books are too introductory (Android in Action is one) or I'm looking in the wrong places. Even the topics of setting up libraries and writing services seem hard to come by. As I see it, there are a few key concepts I'm weak on:
1. How does a service communicate events to apps that are interested without knowledge of an app
2. How can an app be brought to the foreground based on some message received from service
3. How to take an existing app and break into a library (for non-gui or non app specific stuff) and app.
4. How notifications work....

Many thanks in advance,
Dave

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如梦初醒的夏天 2024-12-30 11:07:14

看起来该服务应该“发布”该事件,感兴趣的应用程序应该“订阅”。

该服务正在向用户发布事件。

这里分离逻辑的正确方法是什么?

这取决于你如何定义“正确”。在这种情况下,我可能会将 PendingIntentNotification 一起使用,作为用于启动服务的 Intent 的额外内容。 PendingIntent 实现了 Parcelable,因此可以很好地融入到 Intent extra 中。通过这种方式,客户端可以决定当用户点击通知时会发生什么——所有服务需要做的就是在相关时显示通知

服务如何在不了解应用的情况下将事件传递给感兴趣的应用

此处介绍的用例不相关的应用程序的情况下向感兴趣的应用程序传达事件。您没有将事件从服务传送到应用程序。您正在将服务中的事件传达给用户。用户不是应用程序。

话虽这么说,您可以发送广播,或者让客户端传递一些内容作为 Intent 额外内容,用作回调机制(例如,PendingIntentMessenger )。

如何根据从服务收到的某些消息将应用程序带到前台

该服务调用 startActivity()。请注意,如果用户发现您这样做很烦人(例如,在游戏中弹出一个活动),他们可能会以您不喜欢的方式发泄他们的挫败感。

您目前采用的方法(显示通知)在大多数情况下是正确的。

如何获取现有应用程序并进入库(用于非 GUI 或非应用程序特定的内容)

对于任何值得一提的操作系统,这都无法抽象地回答。

通知如何工作......

文档中对此进行了介绍 以及大多数 Android 入门书籍。

It would seem that the service should be "publishing" the event, and apps that are interested should "subscribe".

The service is publishing the event, to the user.

What is the correct way to separate the logic here?

That depends on how you define "correct". In this case, I'd probably pass the PendingIntent to be used with the Notification as an extra on the Intent you used to start the service. PendingIntent implements Parcelable and therefore goes nicely into an Intent extra. This way the client dictates what happens when the user taps the Notification -- all the Service needs to do is display the Notification when relevant.

How does a service communicate events to apps that are interested without knowledge of an app

That is not relevant for your use case presented here. You are not communicating an event from a service to an app. You are communicating an event from a service to the user. The user is not an app.

That being said, you can send a broadcast, or have the client pass something as an Intent extra that will serve as a callback mechanism (e.g., PendingIntent, Messenger).

How can an app be brought to the foreground based on some message received from service

The service calls startActivity(). Note that users who find you annoying for doing this (e.g., popping up an activity in the middle of their game) may vent their frustration in ways that you will not appreciate.

The approach you are presently taking -- displaying a Notification -- is the correct one in most cases.

How to take an existing app and break into a library (for non-gui or non app specific stuff)

That cannot be answered in the abstract, for any operating system worth mentioning.

How notifications work.....

That is covered in the documentation and most introductory Android books.

这与 Intent 有更多关系,因为它是实际启动其他活动的代码行。

你有一个

Intent toLaunch = new Intent(context, MyBankingActivity.class);

That 会告诉系统“我想对名为:...的活动做一些事情”
作者给出的意图名称已经告诉你会发生什么。

然后,意图会收到几个标志

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP

(长话短说),它们确保活动如果仍在后台某处运行(或者更准确地说,如果它在历史堆栈上),则被带到前面。

然后是 PendingIntent

PendingIntent intentBack = PendingIntent.getActivity(
    context, 0, toLaunch, PendingIntent.FLAG_CANCEL_CURRENT);

我对 PendingIntent 不太熟悉,但我认为它在这里没有正确使用。

至于你的问题:
1)您可以创建意图并让应用程序为其注册侦听器
2)这就是意图所做的事情,它告诉系统将该活动带到前台(或者您可以在意图上使用标志设置其他内容)
3) 取决于应用程序/代码

4) http://developer.android.com /reference/android/app/NotificationManager.html
在那里您还应该找到有关所有其他主题的信息

this has more to do with Intent as it is the line of code that actually starts the other activity.

You have an

Intent toLaunch = new Intent(context, MyBankingActivity.class);

That will tell the system "i want to do something with the activity named: ..."
The name of the intent given by the author already tells you what will happen.

The intent then receives a couple of flags

Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP

(long story short) they make sure the activity is brought to front if it still was running somewhere in the background (or to be more precise, if it was on the history stack).

And then comes the PendingIntent

PendingIntent intentBack = PendingIntent.getActivity(
    context, 0, toLaunch, PendingIntent.FLAG_CANCEL_CURRENT);

Im not so familiar with the PendingIntent but i think its not used the right way here.

As for your questions:
1) you can create intents and have apps register a listener for them
2) thats the thing the intent does, it tells the system to bring that activity to the foreground (or other things you can set with flags on the intent)
3) depends on the app/code

4) http://developer.android.com/reference/android/app/NotificationManager.html
there you should also find info on all the other topics

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文