나는 모든 클라이언트 - 서버 통신을 돌보는 원격 서비스를 만들었습니다. 동일한 통신 소켓을 사용할 별도의 응용 프로그램이 거의없고 응용 프로그램간에 소켓을 "공유"할 수있는 방법이 없기 때문에 서비스를 사용합니다 (알고있는 한).안드로이드 액티비티가 서비스 응답을 기다림
서비스는 훌륭하게 작동하며 소켓 연결을 시작하고이를 통해 int/String을 보낼 수 있지만 readString()과 같은 입력으로 사용할 수는 없습니다.
나는 활동이 서비스의 응답을 기다리지 않기 때문에 문제가 발생한다고 생각합니다. 내 서비스에서 내 readString 메서드의 모든 부분에서 사용자 지정 문자열을 반환하는 동안 테스트했습니다.
및 코드에 대한
...ConnectionRemoteService :
public class ConnectionRemoteService extends Service {
private String deviceID;
private ConnectionThread ct;
@Override
public void onCreate() {
super.onCreate();
//Toast.makeText(this, "Service On.", Toast.LENGTH_LONG).show();
}
@Override
public void onDestroy() {
//Toast.makeText(this, "Service Off.", Toast.LENGTH_LONG).show();
if(ct != null)
ct.close();
}
@Override
public IBinder onBind(Intent intent) {
return myRemoteServiceStub;
}
private ConnectionInterface.Stub myRemoteServiceStub = new ConnectionInterface.Stub() {
public void startConnection(){
WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
deviceID = wm.getConnectionInfo().getMacAddress();
ct = new ConnectionThread(deviceID);
ct.start();
}
public void closeConnection(){
if(ct != null)
ct.close();
}
public void writeInt(int i) throws RemoteException {
if(ct != null)
ct.writeInt(i);
}
public int readInt() throws RemoteException {
if(ct != null)
return ct.readInt();
return 0;
}
public void writeString(String st) throws RemoteException {
if(ct != null)
ct.writeString(st);
}
public String readString() throws RemoteException {
if(ct != null)
return ct.readString();
return null;
}
public String deviceID() throws RemoteException {
return deviceID;
}
public boolean isConnected() throws RemoteException {
return ct.isConnected();
}
};
}
설명 : 당신이 볼 수있는
, 난 단지 "빈"서비스를 시작하고 기다립니다 응용 프로그램과 바인딩 할 수 있습니다. 바인딩 후 소켓 등을 처리 할 ConnectionThread를 만듭니다. 모든 메서드는 소켓을 통해 input \ output 스레드 메서드를 호출합니다.
ConnectionThread :
public class ConnectionThread extends Thread {
private static final int SERVERPORT = 7777;
private static final String SERVERADDRESS = "192.168.1.106";
private String deviceID;
private Socket socket;
private DataInputStream in;
private DataOutputStream out;
private ObjectInputStream inObj;
private ObjectOutputStream outObj;
private boolean isConnected = false;
PingPongThread ppt;
public ConnectionThread(String deviceID) {
super();
this.deviceID = deviceID;
}
@Override
public void run() {
super.run();
open();
}
void open(){
try{
socket = new Socket(SERVERADDRESS,SERVERPORT);
out = new DataOutputStream(socket.getOutputStream());
out.flush();
in = new DataInputStream(socket.getInputStream());
outObj = new ObjectOutputStream(out);
outObj.flush();
inObj = new ObjectInputStream(in);
out.writeUTF(deviceID);
isConnected = true;
ppt = new PingPongThread(SERVERADDRESS, SERVERPORT);
ppt.start();
}
catch(Exception e){
isConnected = false;
System.err.println(e.getMessage());
}
}
public void close(){
try {
if(ppt!=null){
ppt.stopThread();
ppt.notify();
}
if(in!=null)
in.close();
if(out!=null)
out.close();
if(socket!=null)
socket.close();
}
catch(Exception e){
System.err.println(e.getMessage());
}
isConnected = false;
socket=null;
}
public void writeInt(int i){
try {
out.writeInt(i);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public int readInt(){
try {
int i = in.readInt();
return i;
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
public void writeString(String st){
try {
out.writeUTF(st);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public String readString(){
String st = "";
try {
st = in.readUTF();
return st;
} catch (IOException e) {
e.printStackTrace();
}
return st;
}
public boolean isConnected(){
return isConnected;
}
}
설명 :
이내 스레드에서, 내가 소켓을 만들고 나중에 사용하기 위해 인/아웃 개체의 모든를 초기화합니다. ("PingPongThread"를 무시하십시오. 연결을 확인하는 간단한 스레드 일 뿐이므로 다른 포트를 사용하므로 문제가 될 수 없습니다 ...) 다른 모든 메소드는 입력/출력 객체를 사용하는 것만으로 매우 간단합니다. ..
및 주요 활동에 대한
:public class MainLauncherWindow extends Activity {
private ConnectionInterface myRemoteService;
private boolean isServiceBinded = false;
private OnClickListener onclicklistener;
final ServiceConnection conn = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
myRemoteService = ConnectionInterface.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
myRemoteService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_launcher_window);
final Button connectButton = (Button)findViewById(R.id.Connect);
final Button disconnectButton = (Button)findViewById(R.id.Disconnect);
startService(new Intent(getApplicationContext(), ConnectionRemoteService.class));
isServiceBinded = bindService(new Intent("com.mainlauncher.ConnectionRemoteService"),conn,Context.BIND_AUTO_CREATE);
//Connect button
onclicklistener = new OnClickListener(){
public void onClick(View v) {
try {
if(isServiceBinded){
myRemoteService.startConnection();
connectButton.setEnabled(false);
disconnectButton.setEnabled(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
connectButton.setOnClickListener(onclicklistener);
//Disconnect button
onclicklistener = new OnClickListener(){
public void onClick(View v) {
connectButton.setEnabled(true);
disconnectButton.setEnabled(false);
try {
if(isServiceBinded)
myRemoteService.closeConnection();
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
disconnectButton.setOnClickListener(onclicklistener);
//read test button
final Button bt1 = (Button)findViewById(R.id.bt1);
onclicklistener = new OnClickListener(){
public void onClick(View v) {
try {
if(isServiceBinded){
myRemoteService.writeString("Testing");
Toast.makeText(v.getContext(), myRemoteService.readString(), Toast.LENGTH_LONG).show();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
bt1.setOnClickListener(onclicklistener);
}
@Override
public void onBackPressed() {
super.onBackPressed();
if(isServiceBinded){
unbindService(conn);
stopService(new Intent(getApplicationContext(), ConnectionRemoteService.class));
isServiceBinded = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if(isServiceBinded){
unbindService(conn);
stopService(new Intent(getApplicationContext(), ConnectionRemoteService.class));
isServiceBinded = false;
}
}
}
내 주요 활동에서 내가 연결 \ 차단 및 테스트 버튼 버튼을 만들었습니다. 테스트 버튼은 서버 측에 "Testing"문자열을 보냅니다. 서버가 제대로 작동하고 "Testing"String을 가져 와서 다른 문자열을 클라이언트에 반환합니다. "Toast"msg는 항상 비어 있습니다.
- 나는 서비스없이 서버 측을 테스트 했으므로 잘 작동하므로 걱정할 필요가 없습니다.
- 나는 ConnectionThread를 사용하여 테스트 문자열을 반환하고 테스트 문자열을 readString 메서드에서 반환했으며 제대로 작동했기 때문에 스레드가 클라이언트 측에 서비스를 통해 응답을 반환합니다 (모든 체인이 잘 작동 함).
내가 지금 염두에 두어야 할 것은 서비스에서 문자열을 기다리지 않고 문제가 발생한다는 것입니다.
어떤 아이디어가 있습니까?
감사합니다. 리오즈.
"extends AsyncTask"는 내 수업에서 사용할 수 없다. 첫 번째 서비스 확장, 두 번째 확장 스레드 ... AsyncTask를 작동시키는 다른 아이디어는 없나요? – HFDO5
글쎄, 아마도 내부 클래스를 만드는 것이 트릭을 할 수 있습니다. 내부 클래스 doInBackGround()에서 작업을 이동하고 실행하십시오. 또는 스레드를 AsyncTask로 변경하십시오. 스레드와 같습니다. – Ercan
많은 테스트를 마친 후에 제대로 작동 할 수있는 방법을 찾을 수 없습니다. 도움이 될만한 아이디어가 있습니까? – HFDO5