チャレンジ:クライアントアプリケーションを「ソケット上」に作成して、メインアクティビティが閉じられたときに作業が続行され、接続が失われないようにします。
解決策:Androidのサービスを使用してこれを行うことができます。サービスとは何か、どのように機能するかについて多くの記事が書かれているので、詳細には触れず実装を進めません。
このアプリケーションは、3つの最も重要なクラスで構成されています。
- MainActivity-ソケットクライアントの動作の表示が表示されるアクティビティ
- ServiceExchange-サービス自体
- SocketAsync-非同期ソケットクライアント
MainActivity:@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.startService(new Intent(this, ServiceExchange.class));
ここで、サービスを起動し、リスナー「broadcastReceiver」を起動します。リスナーは、サービスから
onDataFromService関数にメッセージを送信します。
ServiceExchange.BROADCAST_ACTIONにメッセージをタグ付けする必要があります。タグを付けないと、失われます。
ServiceExchange: public class ServiceExchange extends Service { private Intent intent; public static final String BROADCAST_ACTION = "com.rheit.base.event";
このサービスは、
SocketAsyncクラスを介したサーバーへの接続の制御、および
BroadcastReceiverを介した
SocketAsyncから
MainActivityへのデータ転送を
実装します。
SocketAsync: class SocketAsync extends AsyncTask<Void, Integer, Void> { public Socket socket; public String message; public Handler threadHandler; public Context parent; public SocketAsync(Handler threadHandler) { this.threadHandler = threadHandler; } @Override protected Void doInBackground(Void... params) { try { if (config.SOCKET_CONNECTED == false) { InetAddress serverAddr = InetAddress .getByName(config.SERVER_ADDR); socket = new Socket(serverAddr, config.SERVER_PORT); config.SOCKET_CONNECTED = true; Intent intent = new Intent(ServiceExchange.BROADCAST_ACTION); intent.putExtra("SERVER_STATUS", true); Message threadMessage = new Message(); threadMessage.what = com.rheit.config.CODE_SOCKET_SERVER_CONNECTED; threadMessage.obj = intent; threadHandler.sendMessage(threadMessage); } } catch (Exception e) { Intent intent = new Intent(ServiceExchange.BROADCAST_ACTION); intent.putExtra("SERVER_STATUS", false); Message threadMessage = new Message(); threadMessage.what = com.rheit.config.ERR_SOCKET_SERVER_UNAVAILABLE; threadMessage.obj = intent; threadHandler.sendMessage(threadMessage); Log.e(SocketAsync.class.toString(), "ERR_SOCKET_SERVER_UNAVAILABLE doInBackground"); } Thread threadWrite = new Thread(new Runnable() { @Override public void run() { send(socket); } }); threadWrite.start();
SocketAsyncタスクを開始すると、サーバーへの接続を開始しました;接続すると、接続したUIにメッセージを送信します:
Intent intent = new Intent(ServiceExchange.BROADCAST_ACTION); intent.putExtra("SERVER_STATUS", true); Message threadMessage = new Message(); threadMessage.what = com.rheit.config.CODE_SOCKET_SERVER_CONNECTED; threadMessage.obj = intent; threadHandler.sendMessage(threadMessage);
次に
、作成した
myUpdateHandlerでServiceExchangeにアクセスし、
sendBroadcastを介してUIにデータを渡します。
case config.CODE_SOCKET_SERVER_CONNECTED:
その後、データが
MainActivityに転送され
ます 。
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { onDataFromService(intent); } }; public void onDataFromService(Intent intent) { Log.d("onDataFromService", intent.getStringExtra("text")); }
アプリケーションを閉じると、
unregisterReceiver関数はリスナーを破棄し、ソケットクライアントから転送されるものはすべて失われます。このため、外部からのデータを通知し、データベースに書き込み、
BroadcastReceiverを使用してデータベースから何かを読み取る必要があることを通知します。