如何编写一个状态图标,可以在Ubuntu以及其他发行版中显示?

所讨论的应用程序执行某些操作(例如将音频连接到网络流),如果这些操作成功,则运行最小化。因此,需要一个状态图标来显示连接状态(例如连接/断开连接)。只有在点击图标时,应用程序窗口才会打开,以便访问其他选项。
使用Python 2.6和pyGtk,我方便地使用了gtk_status_icon来实现这一点。我特意编写了该应用程序,以便在尽可能多的发行版上运行,包括各种Ubuntu版本。我注意到只有在用户安装了可能的依赖项之后,才使用它们。
然而,我现在听说在未来的Ubuntu版本中将不再支持gtk_status_icon。开发人员被要求改用Application Indicators。那么,有什么最佳做法可以确保:
1. 应用程序的本地图标能正确显示; 2. 应用程序在未来的Ubuntu版本中仍然可以运行并显示其图标; 3. 应用程序在其他环境中也可以运行并显示其图标,即在这些环境中没有提供indicator-applet、libappindicator和python-appindicator。
应用程序指示器的回退机制对于未运行indicator-applet的情况下,将无法使用gtk_status_icon。如果没有appindicator模块可供导入,Python解释器将无法运行。我需要为不同的发行版开发不同的版本,还是有更好的方法来解决这个问题。
除了在Ubuntu Wiki中提供的示例之外,我在哪里可以找到关于如何使用ApplicationIndicator的文档?有哪些命令可以用来检查indicator-applet是否正在运行,以避免为Ubuntu和非Ubuntu发行版编写不同的源代码?
4个回答

我认为这里的需求实际上更多地决定了python-appindicator库是否存在。如果存在,它将支持您所需的所有回退情况。它将适当地处理XFCE、KDE和旧版GNOME。在这个答案中有一个很好的例子
appindicator库将使用DBus来检查应用程序指示器渲染进程是否可用。这在Unity上或者indicator-applet正在运行时是成立的。如果可用,它将使用该功能,否则,它将回退到使用具有相同菜单的GtkStatusIcon。
不幸的是,我认为如果您想处理库不可用的情况,您必须保留两个代码路径。不过,我们很乐意帮助将该库引入其他发行版 :)

非常感谢你提供这个非常清晰的答案。这指明了我要在11.04中使我的应用程序运行所必须走的道路。虽然我已经有了一个可以工作的GtkStatusIcon路径,但是为了indicator-applet,我将需要重新开发整个过程。如果我正确理解了你在bug #668375中的评论,我有可能在不创建整个图标主题的情况下使用我的本地图标,对吗? - Takkat
在有时间深入研究AppIndicator编程后,我发现使用jgoguen的建议来检查appindicator模块并不真正有帮助,因为自定义图标在10.04 LTS中无法渲染。请参阅我对bug #668375的评论。 - Takkat
我的回答包含了一个非常简单的方法来解决这个问题。对于我的应用程序来说,它非常有效,并且甚至使得将使用AppIndicators的应用程序移植到Windows变得轻松无痛! - Nathan Osman

我有一个非常好的解决方案,在StackApplet中已经取得了很好的效果 - 我创建了一个功能等效的appindicator模块版本,它在真正的模块不存在时使用gtk.StatusIcon来提供相同的功能。
使用它就像这样简单:
  1. 下载以下文件,并将其命名为appindicator_replacement.py
  2. 将以下内容添加到您的应用程序中:

    try:
        import appindicator
    except ImportError:
        import appindicator_replacement as appindicator
    
就是这样!现在你的应用程序将完美运行,无论是否支持AppIndicators。甚至在Windows上也可以运行,假设你没有其他特定于平台的代码。

注意:该文件以MIT许可证发布,因此您几乎可以将其用于任何事情。


您需要为两者编写代码。您可以使用类似以下代码在您的Python代码中检测appindicator的存在:
have_appindicator = True
try:
    import appindicator
except:
    have_appindicator = False

从那里开始,使用 have_appindicator 来决定你应该使用 appindicator 代码还是 gtk_status_icon 代码。

不幸的是,这也意味着你需要同时拥有一个 Ubuntu 和另一个环境来进行测试。


1然而,可能存在一些环境,python-appindicator已安装但indicator applet未运行。应用程序也需要处理这种情况。 - Takkat
有关此问题,请参阅https://wiki.ubuntu.com/DesktopExperienceTeam/ApplicationIndicators > Custom Fallbacks。默认情况下,如果没有指示器小程序,则会为应用程序指示器提供一个gtk.StatusIcon。 - htorque
我知道备用选项。但我不明白的是,如果指示器小程序没有运行,它怎么能提供备用呢? - Takkat
我想它只是检查了indicator-applet,并在幕后提供了gtk_status_icon的功能。 - jgoguen
1@jgoguen:什么是“it”?我了解从11.04版本开始,Ubuntu/Unity将不再支持gtk_status_icon。其他发行版可能没有“it”。我真的很担心这个问题。 - Takkat
@user3940 "it" 指的是 appindicator,这是处理应用程序指示器的 Python 库。我认为在 Ubuntu 11.04 及以后的版本中,你不需要考虑太多其他事情 - indicator-applet 是必需的,因此会一直运行,并且我已经提供了“备选方案”代码,可以用于与完全没有应用程序指示器的其他平台进行交互。 - jgoguen
@jgoguen: 很遗憾,无法在10.04 LTS上运行 :( - Takkat

for line in os.popen("ps xa"): 
fields = line.split() 
pid = fields[0] 
process = fields[4]

applet_is_running = ( process.find('indicator-applet') > 0 )

这样你就可以检测指示器小程序是否正在运行。你不需要担心Ubuntu 11.04,因为这种情况不会发生。 没有备用方案,因为指示器小程序是一个必需的组件,默认情况下会运行。

感谢您指出如何获取indicator-applet的PID(我已经通过使用pidof来获取其他可能的依赖项),如果没有更好的方法,这将是一个确实不太优雅的方式。据我所见,只有在满足硬件要求的情况下,indicator-applet才能可靠地在Unity中运行。用户可以启动到2D GNOME,并决定不运行indicator-applet。然而,这可能不是我的问题。 - Takkat
我同意你的观点,可能不够“优雅”(但你可以添加所有你想要的装饰:D),但它应该能够正常工作。个人而言,我更喜欢解决方案能够很好地运行,而优雅性则次之 :) - OpenNingia
这个任务似乎在我的14.04系统上没有运行。这种方法已经被取代了吗?相反,有很多/usr/lib/x86_64-linux-gnu/indicator-messages/indicator-messages-service的任务。 - halfer