質問
a)サービスを開始しているものがコードから明らかではありません。それは1回または複数回開始されますか。
現在のコードに基づくと、IPに何かを送信し、結果を読み取り、1つのブロードキャストを送信するように見えます。それだけです。
では、質問です。ライトのステータスを1回だけ更新する必要がありますか、それとも定期的/定期的に更新する必要がありますか?
アイデア
a)ライトのステータスを一度だけ更新する必要があり、UIからトリガーされてUIを更新する場合は、このために特別に設計されたAsyncTaskを使用するとはるかに効果的です。
また、7つの同時AsyncTask(ライトのステータスを並行して更新する場合)を使用するか、ライトのステータスを順次更新して各ライトが更新された後にUIスレッドに報告する1つのAsyncTaskを使用するかはあなた次第です。
b)この場合、ライトのステータスを継続的に追跡する必要がある場合は、サービスを利用することをお勧めします。ただし、このサービスには長時間実行されるスレッドが必要です。したがって、onStartでスレッドを開始する必要があります。
一般に、(たとえば10秒に1回)すべての通信などを引き起こす何らかのメソッドを呼び出す必要があります。
この方法では、Xスレッド(部屋ごとに1つ)に拍車をかけ、これらのスレッドですべての操作(ソケットへの書き込み、読み取り、解析など)を実行するか、この最初のスレッド内でこれらすべてのアクションを実行できます。ここでは、AsyncTaskの場合と同じように、これを並列または直列に実行することができます。
c)また、ライトのステータスを更新する必要がある場合は、すべてのソケットを有効にして再利用し、5秒ごとに再接続しないようにすることもできます。
一般的なコメント
a)非推奨のonStart()を使用しています。onStartCommand()を使用する必要があります
b)プロトタイプである可能性があることは理解していますが、あなたが示したこのコードの品質はかなり低いです。クリーンアップしないと、将来追跡するバグがたくさんあります。
あなたはコードにあります:
- たくさんのマジックナンバー
- 誤った名前の関数(何も表示せず、ソケットの読み取り/書き込み、変換、ブロードキャストの送信を行うDisplayLoggingInfoなど)
- 長いメソッド(DisplayLoggingInfo)
アップデート1
これがあなたのためのサンプルアプリです。これはプロトタイプであることに注意してください。チェックを追加したり、クラスに分けたりすることもできます。
MyService.java
package com.example.servicesample;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import java.lang.Thread;
import android.support.v4.content.LocalBroadcastManager;
public class MyService extends Service implements Runnable {
public static final String ROOM_STATUS_BROADCAST = "com.example.room_status_broadcast";
public static final String ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER = "roomnumber";
public static final String ROOM_STATUS_BROADCAST_EXTRA_STATUS = "status";
static final int NUM_ROOMS = 7;
static final int TIME_FOR_A_REST = 5000; //ms
Thread mThread = null;
Boolean mRunning = false;
@Override
public void onCreate() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
start();
return START_STICKY;
}
@Override
public void onDestroy() {
stop();
}
private synchronized void start()
{
if (mThread != null)
return;
mRunning = true;
mThread = new Thread(this);
mThread.start();
}
private synchronized void stop()
{
if (mThread == null)
return;
mRunning = true;
try
{
mThread.join();
} catch (InterruptedException e) {}
mThread = null;
}
public void run()
{
while (mRunning)
{
for (int i = 0; i < NUM_ROOMS; i++)
updateRoomStatus(i);
try
{
Thread.sleep(TIME_FOR_A_REST);
} catch (InterruptedException e) {}
}
}
Boolean getRoomStatus(int roomNumber)
{
// Do real communication here (instea of just assigning true)
// It makes sense to move all communication to a separate class from here
Boolean newRoomStatus = true;
return newRoomStatus;
}
void updateRoomStatus(int roomNumber)
{
Boolean newRoomStatus = getRoomStatus(roomNumber);
broadcastRoomStatus(roomNumber, newRoomStatus);
}
void broadcastRoomStatus(int roomNumber, Boolean newRoomStatus)
{
Intent intent = new Intent(ROOM_STATUS_BROADCAST);
intent.putExtra(ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER, roomNumber);
intent.putExtra(ROOM_STATUS_BROADCAST_EXTRA_STATUS, newRoomStatus);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
MyActivity.java
package com.example.servicesample;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.Menu;
import com.example.servicesample.MyService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
public class MainActivity extends Activity {
private IntentFilter mIntentFilter = new IntentFilter(MyService.ROOM_STATUS_BROADCAST);
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
MainActivity.this.receivedBroadcast(intent);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startMyService();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
void startMyService()
{
// You can move this code to be executed on a button click or something else
// It will start a service
startService(new Intent(this, MyService.class));
}
@Override
protected void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, mIntentFilter);
}
@Override
protected void onPause()
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver);
super.onPause();
}
private void receivedBroadcast(Intent i) {
Integer roomNumber = i.getIntExtra(MyService.ROOM_STATUS_BROADCAST_EXTRA_ROOM_NUMBER, 0);
Boolean roomStatus = i.getBooleanExtra(MyService.ROOM_STATUS_BROADCAST_EXTRA_STATUS, false);
// Let's do here whatever we want with received status (as example, update UI)
Log.d("SomeTag", "Room number "+roomNumber.toString() + " got new status " + roomStatus.toString());
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicesample"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.servicesample.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyService"/>
</application>
</manifest>