当前位置: 首页 > 知识库问答 >
问题:

显示来自后台启动服务的通知

鄢博简
2023-03-14

所以我正在使用asmack库来侦听传入的xmpp数据包。我已经实现了服务。它启动,绑定,运行一个方法,然后解除绑定。该服务创建PacketListener以获取传入消息,并在新消息传入时显示通知。当应用程序处于活动状态时,这一切都起作用,但当它完全关闭(在窗口列表中滑动)时就不起作用了,它只是在运行服务,PacketListener不启动。但只要重新打开应用程序,它就会立即启动,关闭所有通知。我正在寻找得到这些通知,因为他们进来,而不是服务暂停,如果你愿意。服务的代码如下:

package com.jayseeofficial.xmpp.service;

import java.io.File;
import java.util.ArrayList;

import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;
import android.widget.Toast;

import com.jayseeofficial.xmpp.MainActivity;
import com.jayseeofficial.xmpp.Program;
import com.jayseeofficial.xmpp.R;
import com.jayseeofficial.xmpp.objects.Contact;
import com.jayseeofficial.xmpp.preferences.Preferences;

public class XMPPService extends Service {

    private Connection conn = null;
    private boolean loggedIn = false;

    private final XMPPBinder binder = new XMPPBinder();

    private Handler handler;

    @Override
    public IBinder onBind(Intent arg0) {
        handler = new Handler(getMainLooper());
        return binder;
    }

    public class XMPPBinder extends Binder {
        public XMPPService getService() {
            return XMPPService.this;
        }
    }

    public void logIn() {
        new LogInTask().execute();
    }

    public boolean isLoggedIn() {
        return loggedIn;
    }

    private ConnectionConfiguration getConnectionConfiguration() {
        ConnectionConfiguration config = new ConnectionConfiguration(
                Preferences.Account.getServer(), Preferences.Account.getServerPort());
        config.setSASLAuthenticationEnabled(true);
        config.setCompressionEnabled(true);
        config.setSecurityMode(SecurityMode.enabled);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            config.setTruststoreType("AndroidCAStore");
            config.setKeystoreType("AndroidCAStore");
            config.setTruststorePassword(null);
            config.setTruststorePath(null);
        } else {
            config.setTruststoreType("BKS");
            String path = System.getProperty("javax.net.ssl.trustStore");
            if (path == null) {
                path = System.getProperty("java.home") + File.separator + "etc" + File.separator
                        + "security" + File.separator + "cacerts.bks";
            }
            config.setTruststorePath(path);
        }
        return config;
    }

    private void showNotification() {
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
                .setContentTitle("XMPP+").setContentText("running")
                .setSmallIcon(R.drawable.speech_bubble);

        Intent i = new Intent(this, MainActivity.class);

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(MainActivity.class);
        stackBuilder.addNextIntent(i);

        // Assign the intent
        mBuilder.setContentIntent(stackBuilder.getPendingIntent(9127,
                PendingIntent.FLAG_UPDATE_CURRENT));

        NotificationManager mgr = (NotificationManager) this
                .getSystemService(Context.NOTIFICATION_SERVICE);

        Notification n = mBuilder.build();

        n.flags |= Notification.FLAG_ONGOING_EVENT;

        mgr.notify(1,n);
    }

    private void hideNotification() {
        // TODO Implement hideNotification in XMPPService
    }

    private class LogInTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            try {

                showNotification();

                // Set up and log in
                conn = new XMPPConnection(getConnectionConfiguration());
                conn.connect();
                conn.login(Preferences.Account.getUsername(), Preferences.Account.getPassword());

                // Set up to receive messages
                PacketFilter filter = new PacketTypeFilter(Message.class);
                conn.addPacketListener(new XMPPMessagePacketListener(), filter);
                conn.sendPacket(new Presence(Type.available));

                final ArrayList<Contact> allContacts = new ArrayList<Contact>();

                // Populate contact list
                for (RosterEntry re : conn.getRoster().getEntries()) {
                    Log.d("Roster entry: ", re.getUser() + ": " + re.getName());
                    Contact c = new Contact();
                    if (re.getName() == null) {
                        c.setName(re.getUser());
                    } else {
                        c.setName(re.getName());
                    }
                    c.setAddress(re.getUser());

                    allContacts.add(c);
                }

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        Program.contacts.addAll(allContacts);
                    }
                });

                loggedIn = true;
            } catch (XMPPException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void ignored) {
            if (loggedIn) {
                Toast.makeText(XMPPService.this, "Logged in successfully", Toast.LENGTH_LONG)
                        .show();
            } else {
                Toast.makeText(XMPPService.this, "Failed to log in", Toast.LENGTH_LONG).show();
            }
        }
    }

    private class XMPPMessagePacketListener implements PacketListener {
        @Override
        public void processPacket(Packet packet) {
            Message m = (Message) packet;
            if (m.getBody() != null) {
                com.jayseeofficial.xmpp.objects.Message message = new com.jayseeofficial.xmpp.objects.Message();
                message.setRecipient(Preferences.Account.getUsername() + "@"
                        + Preferences.Account.getServer());
                String fullSender = m.getFrom();
                String address = fullSender.substring(0, fullSender.indexOf('/'));
                message.setSender(address);
                message.setContents(m.getBody());
                Program.showMessageNotification(message, 9127);
            }
        }

    }
}

这里是启动/绑定服务的代码:

public static void init() {
        if (!initialized) {
            // Call other portions of init code first
            SmackAndroid.init(context);
            Preferences.init();

            // Set up our variables
            contacts = GlazedLists.threadSafeList(new BasicEventList<Contact>());

            // Start up the xmpp connection
            Intent ixmpp = new Intent(context, XMPPService.class);
            context.startService(ixmpp);
            context.bindService(ixmpp, xmppConnection, Context.BIND_AUTO_CREATE);

            initialized = true;
        }
    }

所以正如我所说的,我想在前台活动关闭时从后台运行的服务接收通知。有什么办法可以做到这一点吗?也许有它自己的过程?其它的呢?

编辑:正在进行的通知会在点击后继续使用,以防你想知道

共有1个答案

方俊
2023-03-14

使用startforeground方法http://developer.android.com/reference/android/app/service.html#startforeground%28int,%20android.app.notification%29

在服务的onCreate中

public void onCreate() {

 startForeground (int id, Notification notification)
}
 类似资料:
  • 编辑 我的通知是这样创建的,到目前为止,它在数千个API<26的android设备上工作:

  • 问题内容: 我有一个flask应用程序,目前正在以以下方式启动: 当我运行此脚本时,它通过打印成功执行: 但是它永远不会返回,如果我执行CTRL-C,服务器将停止。我正在尝试将其部署到生产环境中,并希望在后台运行此启动,只要服务器启动,进程就可以启动。 做这个的最好方式是什么? 问题答案: 可能是使其在后台运行的最简单方法。就是说,如果你要将其转入生产环境(如@LukasGraf所提到的那样,则不

  • 所以,我有一个main活动,它有一个启动服务的按钮,MyService。我希望该服务显示带有自定义标题、文本、图标等的通知。该服务是一个前台服务。不是绑定服务。一切正常,但唯一的一点是关于我的通知是不断显示“点击获取更多信息”,点击它会引导我进入应用程序的设置页面。尽管我的主要活动是悬而未决的。 我想要的是有一个带有自定义标题、文本、图标和停止服务的操作的通知。 这是我的主要活动。java类 我的

  • 问题内容: 我正在尝试在收到C2DM消息时显示一个简单的通知。服务提供给UI,但仍在主线程上运行。我见过有人声称您可以通过服务创建和显示通知。 } 我不知道为什么会抛出该异常。 问题答案: 首先,引发异常是因为创建的通知没有引用该对象的视图对象(contentView属性设置为null)。您必须在显示通知之前调用setLatestEventInfo。 其次,不赞成使用您使用的构造函数。请使用Not

  • 这是我遇到的问题,与设计和实现相关: 我有一个接受 POST 请求的 REST Web 服务。没什么特别的。它当前以同步方式响应。 但是,此web服务将启动一个后台进程,这可能需要很长时间。 我不希望此服务在 30 分钟后响应。 相反,它应该立即向客户端返回一个ack响应,仅此而已(即使在30分钟后,也不会有更多的信息要发送)。 我如何在泽西实施这种行为? 我读了那一页https://jersey

  • 所以,我有一个拥有50000用户的应用程序。最近我更新了我的android studio,把SDK编译成了27。我做了一些改变,以支持android 8的变化,包括通知的变化(例如,通知应该有唯一的渠道)。在Android One手机上测试了这个(运行android 8)。一切都很顺利。在更新playstore上的应用程序后,我在android 8设备上看到了这些崩溃(主要是谷歌Pixel手机)