Как запустить socket.io как службу переднего плана, чтобы оставаться на связи и прослушивать сообщения - PullRequest
4 голосов
/ 08 мая 2019

Я использую это приложение-источник для общения с другими устройствами. Но как сделать так, чтобы он запускался как Сервис, чтобы я мог запустить сервис переднего плана. Нужно ли переписывать MainFragment и LoginActivity в Сервисе?

приложение socket.io socket.io-android-chat

Я пробовал что-то подобное в классе SocketService, что еще мне нужно включить в Service for App, чтобы получать уведомления, даже если приложение закрыто.

public class SocketService extends Service {
    private Socket mSocket;
    public static final String TAG = SocketService.class.getSimpleName();
    private static final String NOTIFICATION_CHANNEL_ID_DEFAULT = "App running in background";
    String GROUP_KEY_WORK_EMAIL = "com.android.example.WORK_EMAIL";
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this, "on created", Toast.LENGTH_SHORT).show();

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setGroup(GROUP_KEY_WORK_EMAIL);
        Notification notification = builder.build();
        NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
        // Set big text style.
        builder.setStyle(bigTextStyle);
        startForeground(3, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "start command", Toast.LENGTH_SHORT).show();
        try {
            mSocket = IO.socket(Constants.CHAT_SERVER_URL);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        mSocket.on("newMessageReceived", onNewMessage);
        mSocket.connect();
        return START_STICKY;
    }

    private Emitter.Listener onNewMessage = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            JSONObject data = (JSONObject) args[0];
            String username;
            String message;
            try {
                username = data.getString("username");
                message = data.getString("message");
            } catch (JSONException e) {
                Log.e(TAG, e.getMessage());
                return;
            }

            Log.d(TAG, "call: new message ");
            setNotificationMessage(message, username);
        }
    };

    public void setNotificationMessage(CharSequence message, CharSequence title) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
        builder.setSmallIcon(R.drawable.ic_launcher);
        builder.setContentTitle(title);
        builder.setContentText(message);
        NotificationManagerCompat nm = NotificationManagerCompat.from(this);
        nm.notify(3, builder.build());
    }
}

Ответы [ 2 ]

2 голосов
/ 03 июня 2019

вы не должны использовать службу переднего плана для получения уведомлений, когда ваше приложение находится в фоновом режиме

, вместо этого вы должны использовать push-уведомление firebase

однакоесли вам все еще нужно использовать сокетное соединение в службе переднего плана

, просто создайте одноэлементный класс для обработки всех соединений сокетов и используйте его в качестве службы переднего плана, как показано ниже

 public class SocketManger {


        private  static SocketManger socketManger;

        Socket socket;
        Callback<Boolean> onConnect;

        public void init(Callback<Boolean> onConnect){
            this.onConnect = onConnect;
            connectToSocket();
            listenToPublicEvents();
        }

        private void connectToSocket(){
            try{
                IO.Options opts = new IO.Options();
                //optional parameter for authentication
                opts.query = "token=" + YOUR_TOKEN;
                opts.forceNew = true;
                opts.reconnection = true;
                opts.reconnectionDelay = 1000;
                socket = IO.socket(YOUR_URL, opts);
                socket.connect();

            }
            catch(URISyntaxException e){

                throw new RuntimeException(e);
            }
        }

        private void listenToPublicEvents(){
            socket.on(Socket.EVENT_CONNECT, args -> {
                if(onConnect!=null)
                    onConnect.onResult(true);
                    } );

            socket.on(Socket.EVENT_DISCONNECT, args ->{
                    if(onConnect!=null)
                    onConnect.onResult(false);
                   });
        }


        public void emit(String event, JSONObject data, Ack ack){
            socket.emit(event, new JSONObject[]{data}, ack);
        }


        public void on(String event, Emitter.Listener em){
            socket.on(event, em);
        }


        public static SocketManger getSocketManger() {
            if(socketManger == null){
                socketManger = new SocketManger();
            }
            return socketManger;
        }


        public boolean isConnected(){
            return socket!=null && socket.connected();
        }

        public void onDestroy() {
            onConnect = null;
            socket.disconnect();
        }

    public interface Callback<T> {
      void onResult(T t);
     }

    }

, и добавьтеэтот код для службы переднего плана

SocketManager socketManger = SocketManger.getSocketManger();

    @Override
    public void onCreate() {
      socketManger.init(this::onSocketEvent);
   }

 public void onSocketEvent(boolean connect){
    //your code when the socket connection connect or disconnect
    }

и обязательно отключите сокет при уничтожении службы

     @Override
    public void onDestroy() {
        socketManger.onDestroy()
        super.onDestroy();
    }
1 голос
/ 04 июня 2019

Вы можете запустить его из пользовательского класса Application в методе onCreate, если хотите, чтобы служба запускалась сразу после запуска приложения.

Или вы можете запустить его с любого вида деятельности, например.из метода onCreate, если вы хотите запустить службу из определенного действия.

Или вы можете начать с BroadcastReceiver при загрузке устройства.В этом случае используйте действие BOOT_COMPLETED:

Чтобы запустить службу, просто используйте этот код в любом месте, где вы хотите запустить службу:

Intent intent = new Intent(context, SocketService.class);


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    context.startForegroundService(intent);
} else {
    context.startService(intent);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...