最初に、サーバーにデータを送信するアクティビティに非同期タスクを実装しました。しかし、アクティビティを変更すると接続が失われました。これを回避するために、私のアプローチは、ネットワーク操作を集中化してサーバーにデータを送信するサービスを実装することでした。このサービスのコードは以下のとおりです。
import Java.io.BufferedWriter;
import Java.io.OutputStreamWriter;
import Java.io.PrintWriter;
import Java.net.InetAddress;
import Java.net.Socket;
import Android.app.Service;
import Android.content.Intent;
import Android.os.Binder;
import Android.os.IBinder;
import Android.util.Log;
import Android.widget.Toast;
public class SocketService extends Service {
public static final String SERVERIP = ""; //your computer IP address should be written here
public static final int SERVERPORT = 5000;
PrintWriter out;
Socket socket;
InetAddress serverAddr;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
System.out.println("I am in Ibinder onBind method");
return myBinder;
}
private final IBinder myBinder = new LocalBinder();
TCPClient mTcpClient = new TCPClient();
public class LocalBinder extends Binder {
public SocketService getService() {
System.out.println("I am in Localbinder ");
return SocketService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("I am in on create");
}
public void IsBoundable(){
Toast.makeText(this,"I bind like butter", Toast.LENGTH_LONG).show();
}
public void sendMessage(String message){
if (out != null && !out.checkError()) {
System.out.println("in sendMessage"+message);
out.println(message);
out.flush();
}
}
@Override
public int onStartCommand(Intent intent,int flags, int startId){
super.onStartCommand(intent, flags, startId);
System.out.println("I am in on start");
// Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
Runnable connect = new connectSocket();
new Thread(connect).start();
return START_STICKY;
}
class connectSocket implements Runnable {
@Override
public void run() {
try {
//here you must put your computer's IP address.
serverAddr = InetAddress.getByName(SERVERIP);
Log.e("TCP Client", "C: Connecting...");
//create a socket to make the connection with the server
socket = new Socket(serverAddr, SERVERPORT);
try {
//send the message to the server
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
Log.e("TCP Client", "C: Sent.");
Log.e("TCP Client", "C: Done.");
}
catch (Exception e) {
Log.e("TCP", "S: Error", e);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
try {
socket.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
socket = null;
}
}
Rotator.Javaは、このサービスにバインドするアクティビティです。以下は私の活動からのコードの一部です。
private ServiceConnection mConnection = new ServiceConnection() {
//EDITED PART
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
mBoundService = ((SocketService.LocalBinder)service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
mBoundService = null;
}
};
private void doBindService() {
bindService(new Intent(Rotator.this, SocketService.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
if(mBoundService!=null){
mBoundService.IsBoundable();
}
}
private void doUnbindService() {
if (mIsBound) {
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector(this, new GestureListener());
setContentView(R.layout.activity_rotator);
//Binding the activity to the service to perform client-server operations
//start service on create
startService(new Intent(Rotator.this,SocketService.class));
doBindService();
...........
...........
}
@Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
このサービスはバックグラウンドで実行されるため、サーバーにデータを送信する場合は次を使用します
if(mBoundService!=null)
{
mBoundService.sendMessage("right");
}
コードは正しいです。唯一の間違いは、onServiceConnected()メソッドで1回、onCreate()メソッドでもう1回サービスを開始しようとしていたことです。
ランチャーアクティビティのonCreate()メソッドでのみサービスを開始するようにコードを変更しました。残りのアクティビティは、doBindService()メソッドを使用してサービスに直接バインドします
サービスがActivity
にバインドされている場合、アクティビティが停止すると強制終了されます。これはActivity
のみのバックグラウンドサービスのようです。したがって、実行し続けるには、Service
クラスにonStartCommand()
メソッドを実装し、this.START_STICKY
。この方法でサービスを管理します。