2016-11-15 13 views
4

私はAndroidの開発に慣れていません。アプリケーションがバックグラウンドサービスを介してアクティブでなくてもソケットイベントを検出できるようにしたいと思います(たとえば、プッシュ通知を行うことができます。 Whatsappと他の人がそれをする)。Androidでバックグラウンドサービスとしてソケットイベントを処理する方法は?

バックグラウンドサービスと、サービスを開始するアプリケーションクラスを実装しましたが、バックグラウンドサービスでソケットイベントをRunnableタスクとして配置する方法と場所を固定しました。

下記のsocket.io android chatプロジェクトのサンプルを修正し、サービスとアプリケーションクラスを追加しました。

ChatApplication.java

package com.github.nkzawa.socketio.androidchat; 

import android.app.Application; 
import android.content.Intent; 
import android.content.res.Configuration; 

import io.socket.client.IO; 
import io.socket.client.Socket; 

import java.net.URISyntaxException; 

public class ChatApplication extends Application { 

    @Override 
    // called when the application is starting, before any other application objects have been created 
    public void onCreate() { 
     super.onCreate(); 

     // represents our background service 
     Intent background = new Intent(this, SocketBackgroundService.class); 
     startService(background); 
    } 

    private Socket mSocket; 
    { 
     try { 
      mSocket = IO.socket(Constants.CHAT_SERVER_URL); 
     } catch (URISyntaxException e) { 
      throw new RuntimeException(e); 
     } 
    } 

    public Socket getSocket() { 
     return mSocket; 
    } 
} 

SocketBackgroundService.java

package com.github.nkzawa.socketio.androidchat; 

import android.app.Service; 
import android.content.Intent; 
import android.os.IBinder; 
import android.util.Log; 

public class SocketBackgroundService extends Service { 
    private boolean isRunning; 
    private Thread backgroundThread; 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 

    @Override 
    public void onCreate() { 
     this.isRunning = false; 
     this.backgroundThread = new Thread(myTask); 
    } 

    private Runnable myTask = new Runnable() { 
     @Override 
     public void run() { 
      // do something in here 
      Log.i("INFO", "SOCKET BACKGROUND SERVICE IS RUNNING"); 

      //TODO - how to handle socket events here? 
      //How do I do something like mSocket.on(Socket.EVENT_CONNECT,onConnect); here? 
     } 
    }; 

    @Override 
    public void onDestroy() { 
     this.isRunning = false; 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     if(!this.isRunning) { 
      this.isRunning = true; 
      this.backgroundThread.start(); 
     } 

     return START_STICKY; 
    } 
} 

答えて

3

、あなたのアプリケーションが停止した後も生きているソケットが必要な場合。ソケットをバックグラウンドサービスに移動し、サービス内でソケットイベントを追加することができます。

+0

シンタックスは、私が実際に把握しようとしているものです。どのようにSアプリケーションからバックグラウンド・サービスのRunnable関数に移動します。 :) – Woppi

+0

このプライベートソケットmSocketを移動します。 { try { mSocket = IO.socket(Constants.CHAT_SERVER_URL); } catch(URISyntaxException e){ 新しいRuntimeException(e)をスローします。 } } – Ashish

+0

to SocketBackgroundService。 – Ashish

2

メインスレッドでソケットを開きます。メインスレッドでソケット接続を開かないと、UIスレッドで大量の作業が発生するために発生するANR(アプリケーションが応答しない)エラーが発生します。 UIスレッドを5秒以上ブロックします。ですから、サービス内のスレッドでソケット接続を開くことをお勧めします。
ここ プレーンソケットを使用した例である。

  1. バックグラウンドサービスにスレッドを開始するための1つのサービス・クラスを作成するに
  2. ソケット通信

    ための別のクラスを作成スレッド
  3. にソケット接続を開くためのThreadクラスに作成

    public class SocketBackgroundService extends Service { 
    
    private SocketThread mSocketThread; 
    
    @Override 
    public IBinder onBind(Intent intent) { 
        return null; 
    } 
    
    @Override 
    public void onCreate() { 
    
        mSocketThread = SocketThread.getInstance(); 
    } 
    
    
    @Override 
    public void onDestroy() { 
        //stop thread and socket connection here 
    } 
    
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
        if (mSocketThread.startThread) { 
        } else { 
         stopSelf(); 
        } 
    
        return START_STICKY; 
    } 
    } 
    
    public class SocketThread extends Thread { 
    
    private static SocketThread mSocketThread; 
    private SocketClient mSocketClient; 
    
    private SocketThread() { 
    } 
    
    // create single instance of socket thread class 
    public static SocketThread getInstance() { 
        if (mSocketThread == null)//you can use synchronized also 
        { 
         mSocketThread = new SocketThread(); 
        } 
        return mSocketThread; 
    } 
    
    
    public boolean startThread() { 
          =new SocketClient(); 
        if (socketClient.isConnected()) { 
         mSocketThread.start() 
         return true; 
        } 
        return false; 
    } 
    
    @Override 
    public void run() { 
        super.run(); 
        while (mSocketClient.isConnected()) { 
         // continue listen 
        } 
        // otherwise remove socketClient instance and stop thread 
    } 
    
    public class SocketClient { 
        //write all code here regarding opening, closing sockets 
        //create constructor 
        public SocketClient() { 
         // open socket connection here 
        } 
    
        public boolean isConnected() { 
         return true; 
        } 
    } 
    
+1

こんにちはサム、私はアンドロイドの開発に慣れていて、私のコードがメインスレッドで実行されていることをどの部分で検出したのですか?私はバックグラウンドサービスを実行しており、上記のAshishのアドバイスによってソケットを聞くことができます。私はあなたがこの問題を言及したように改善したいと思います。ここに私の作業コードがあります:https://gist.github.com/arvi/a31843d26dcd1fd69c32bbe2bb7130d7アドバイスが必要な場合は、どうもありがとう、本当にありがとうございます。 :) – Woppi

+1

こんにちはWoppi、このコードは私によく見えます。あなたは本当にうまくコードを作成し、非常によく改善されました。このコードに関する問題がありますか? –

+0

こんにちは@Sam、私はあなたのコードを見直す時間を割いてくれて本当にありがとう。私にとっては大きな出来事です。だから今私はスレッドをうまく処理したことは明らかです。私はまた、ちょっとしたコミュニティでちょっとした意見を共有しています(私はarviioです)https://androidchat.slack.com/messages/beginners/フィードバックを得るためには、バインドの代わりにブロードキャストレシーバを使用することをお勧めしましたサービス。これで、私はAppSocketEventsとServiceConnをアクティビティクラスで取り除くことができます...そして、すべてのサービスを使用するだけです。私はまだEventBusを見てきました。私が正しい方法でやっているなら、私の問題は私の自信です。 – Woppi