如何在应用程序运行时,在状态栏中显示图标,包括后台运行时?

29
我希望在我的应用程序运行时,包括后台运行时,在状态栏中放置一个图标。我该如何实现这一点?
4个回答

21

您可以使用通知(Notification)和通知管理器(NotificationManager)来实现此功能。然而,确保在应用程序未运行时获取可靠的通知方式是困难的。

您可以通过类似以下方式获得所需的基本功能:

Notification notification = new Notification(R.drawable.your_app_icon,
                                             R.string.name_of_your_app, 
                                             System.currentTimeMillis());
notification.flags |= Notification.FLAG_NO_CLEAR
                   | Notification.FLAG_ONGOING_EVENT;
NotificationManager notifier = (NotificationManager)
     context.getSystemService(Context.NOTIFICATION_SERVICE);
notifier.notify(1, notification);

这段代码必须放在确保应用程序启动时会被执行的地方,可能是在应用程序自定义的Application对象的onCreate()方法中。

然而,在此之后情况就比较棘手了。应用程序可能会在任何时候被终止。因此,您可以尝试将某些内容放入Application类的onTerminate()中,但不能保证其一定被调用。

((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)).cancel(1);

将是移除图标所需的内容。


5
“Notification”在API 11级中已过时。请改用“Notification.Builder”。 - Hartmut Pfitzinger
如果您使用Service,则无需手动删除通知。当服务停止时,通知将自动删除。(“但是,如果您在服务仍在前台运行时停止服务,则通知也将被删除。”https://developer.android.com/guide/components/services.html#Foreground) - domids

10
对于新的API,您可以使用NotificationCompat.Builder
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.mipmap.ic_launcher)
    .setContentTitle("Title");
Intent resultIntent = new Intent(this, MyActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;

mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(NOTIFICATION_ID, notification);

只要您的应用程序正在运行且有人手动关闭您的应用程序,通知就会显示。您可以通过调用来取消通知 -
mNotifyMgr.cancel(NOTIFICATION_ID);

MyActivity.class的内容将是什么?@mjosh - Sarah cartenz
@Sarahcartenz 任何你想要的东西。 - mihirjoshi
如果我不定义这样的类,或者保持它为空,会怎么样呢?例如,我不希望在通知被按下后执行任何操作。 - Sarah cartenz
1
请删除此行代码:mBuilder.setContentIntent(resultPendingIntent); - mihirjoshi

6
请查看Dev Guide "创建状态栏通知"。
实现只有应用程序运行时才保留图标的目标的一种方法是在onCreate()中初始化通知,在您的onPause()方法中仅在isFinishing()返回true时调用cancel(int)
例如:
private static final int NOTIFICATION_EX = 1;
private NotificationManager notificationManager;

@Override
public void onCreate() {
    super.onCreate();

    notificationManager = (NotificationManager) 
        getSystemService(Context.NOTIFICATION_SERVICE);

    int icon = R.drawable.notification_icon;
    CharSequence tickerText = "Hello";
    long when = System.currentTimeMillis();

    Notification notification = new Notification(icon, tickerText, when);

    Context context = getApplicationContext();
    CharSequence contentTitle = "My notification";
    CharSequence contentText = "Hello World!";
    Intent notificationIntent = new Intent(this, MyClass.class);
    PendingIntent contentIntent = PendingIntent.getActivity(this, 
        0, notificationIntent, 0);

    notification.setLatestEventInfo(context, contentTitle, 
        contentText, contentIntent);

    notificationManager.notify(NOTIFICATION_EX, notification);
}

@Override
protected void onPause() {
    super.onPause();
    if (isFinishing()) {
        notificationManager.cancel(NOTIFICATION_EX);
    }
}

这仅仅会展示给你某个活动是否正在运行,而不是应用程序是否仍在运行。 - Greg Giacovelli
@Greg:没错,这个示例代码只能正确处理一个活动应用程序。更难的是确定系统何时终止了应用程序。正如你所提到的,自定义“Application”类可能是最好的代码位置,因为它在整个应用程序的生命周期中都存在。清除通知将会很困难,因为在低内存条件下,系统可能会任意决定终止应用程序的进程。您可以尝试创建一个服务来监视状态,因为当更多内存可用时,系统将尝试重新启动该服务。 - Brian
如果您从onPause中删除notificationManager.cancel(NOTIFICATION_EX);,则通知将一直停留在通知栏中,直到应用程序完全停止。 - Vettiyanakan

4

它真的起作用。 我根据上面的例子创建了一个方法:

private void applyStatusBar(String iconTitle, int notificationId) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(iconTitle);
Intent resultIntent = new Intent(this, ActMain.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR|Notification.FLAG_ONGOING_EVENT;

NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(notificationId, notification);}

应该这样调用:applyStatusBar("状态栏测试", 10);

我可以问一下,ActMain.class 的内容是什么? - Sarah cartenz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接