teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

8

サーバ側不要setContentView削除

2019/01/31 13:54

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -11,7 +11,7 @@
11
11
  @Override
12
12
  protected void onCreate(Bundle savedInstanceState) {
13
13
  super.onCreate(savedInstanceState);
14
- setContentView(R.layout.activity_server);
14
+ //setContentView(R.layout.activity_server);
15
15
  try {
16
16
  new Thread(new Server("0.0.0.0",8080)).start();
17
17
  } catch (IOException e) {

7

クライアントレイアウト追加

2019/01/31 13:54

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -236,4 +236,37 @@
236
236
  }
237
237
  }
238
238
  }
239
+ ```
240
+ ```xml(R.layout.activity_client.xml)
241
+ <?xml version="1.0" encoding="utf-8"?>
242
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
243
+ xmlns:tools="http://schemas.android.com/tools"
244
+ android:layout_width="match_parent"
245
+ android:layout_height="match_parent"
246
+ android:orientation="vertical"
247
+ tools:context=".ClientActivity">
248
+ <TextView
249
+ android:id="@+id/question"
250
+ android:layout_width="match_parent"
251
+ android:layout_height="wrap_content"
252
+ android:textAppearance="@style/TextAppearance.AppCompat.Large"
253
+ android:text="問題文"/>
254
+ <EditText
255
+ android:id="@+id/answer"
256
+ android:layout_width="match_parent"
257
+ android:layout_height="wrap_content"
258
+ android:textAppearance="@style/TextAppearance.AppCompat.Large"
259
+ android:text="回答欄"/>
260
+ <TextView
261
+ android:id="@+id/result"
262
+ android:layout_width="match_parent"
263
+ android:layout_height="wrap_content"
264
+ android:textAppearance="@style/TextAppearance.AppCompat.Large"
265
+ android:text="結果"/>
266
+ <Button
267
+ android:id="@+id/finalAnswer"
268
+ android:layout_width="wrap_content"
269
+ android:layout_height="wrap_content"
270
+ android:text="回答送信"/>
271
+ </LinearLayout>
239
272
  ```

6

サーバ側コード修正, 実機サーバ<->telnetクライアントで簡単な動作確認.

2019/01/31 13:51

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -8,101 +8,100 @@
8
8
 
9
9
  ```java
10
10
  public class ServerActivity extends AppCompatActivity {
11
+ @Override
12
+ protected void onCreate(Bundle savedInstanceState) {
13
+ super.onCreate(savedInstanceState);
14
+ setContentView(R.layout.activity_server);
15
+ try {
16
+ new Thread(new Server("0.0.0.0",8080)).start();
17
+ } catch (IOException e) {
18
+ e.printStackTrace();
19
+ }
20
+ }
21
+ private class Server implements Runnable {
22
+ private String host;
23
+ private int port;
24
+ Server(String host, int port) throws IOException {
25
+ this.host = host;
26
+ this.port = port;
27
+ }
11
28
  @Override
29
+ public void run() {
12
- protected void onCreate(Bundle savedInstanceState) {
30
+ Log.d("Server", "アドレス="+host+", ポート="+port);
13
- super.onCreate(savedInstanceState);
31
+ ServerSocket ss = null;
14
- setContentView(R.layout.activity_server);
15
- try {
32
+ try {
16
- new Thread(new Server(8080)).start();
33
+ ss = new ServerSocket();
34
+ ss.bind(new InetSocketAddress(host, port));
17
- } catch (IOException e) {
35
+ while(true) {
36
+ Log.d("Server.run", "accept()");
18
- e.printStackTrace();
37
+ Socket s = ss.accept();
38
+ Log.d("Server.run", "s="+s);
39
+ new Questioner().execute(s);
19
40
  }
41
+ } catch (IOException e) {
42
+ Log.e("Server.run", "IOException", e);
43
+ } finally {
44
+ if(ss != null) try { ss.close(); } catch (IOException ignore) {}
45
+ }
20
46
  }
21
- //サーバ. 延々と受付待ちです.
47
+ }
22
- private class Server implements Runnable {
48
+ private class Questioner extends AsyncTask<Object, Object, String> {
49
+ @Override
50
+ protected String doInBackground(Object... objects) {
51
+ Socket s = (Socket)objects[0]; //パラメータ1つめは Socket.
52
+ try {
53
+ BufferedWriter w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
54
+ BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
55
+ Question q;
56
+ for(int number=1; (q = createQuestion(number)) != null; number++) {
57
+ Log.d("Questioner.doInBackground", "問題送信 linecount="+q.linecount+", text="+q.text);
58
+ w.write(q.linecount+"\n");
59
+ w.write(q.text);
60
+ w.flush();
23
- ServerSocket ss;
61
+ String result;
62
+ do {
24
- Server(int port) throws IOException {
63
+ Log.d("Questioner.doInBackground", "回答受信");
25
- ss = new ServerSocket(port);
64
+ String answer = r.readLine();
65
+ Log.d("Questioner.doInBackground", "answer="+answer);
66
+ if(answer == null) return null;
67
+ result = answer.equals(q.correctAnswer) ? "OK" : "NG";
68
+ Log.d("Questioner.doInBackground", "判定送信 result="+result);
69
+ w.write(result + "\n");
70
+ w.flush();
71
+ } while (result.equals("NG"));
26
72
  }
73
+ Log.d("Questioner.doInBackground", "終了送信");
74
+ w.write("0\n");
27
- @Override
75
+ w.flush();
28
- public void run() {
76
+ } catch (IOException e) {
29
- try {
30
- while(true) {//延々と受付待ち
31
- Socket s = ss.accept();//サーバは受付だけ
32
- new Questioner().execute(s);//受付したら, 後は専用スレッドに任せます.
77
+ Log.e("Questioner.doInBackground", "異常", e);
78
+ } finally {
79
+ try { s.close(); } catch(IOException ignore) {}
33
- }
80
+ }
34
- } catch (IOException e) {
35
- e.printStackTrace();
36
- } finally {
81
+ return null;
37
- try { ss.close(); } catch (IOException ignore) {}
38
- }
39
- }
40
82
  }
41
- //クライアントと会話する質問者. パラメータの Socket は既にクライアントと繋がっています.
42
- private class Questioner extends AsyncTask<Object, Object, String> {
43
- @Override
44
- protected String doInBackground(Object... objects) {
45
- Socket s = (Socket)objects[0];//パラメータ1つめは Socket.
46
- try {
47
- BufferedWriter w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
48
- BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
49
- Question q;
83
+ private class Question {
50
- for(int number=1; (q = createQuestion(number)) != null; number++) { //問題が無くなるまで繰り返す
51
- //まずクライアントに問題を送ります. まず行数を送り, 次にその行数文の問題文を送ります. 改行を忘れないでください.
52
- //これ以降のプロトコルは仕様次第です.
53
- w.write(q.linecount+"\n");
84
+ final int linecount;
54
- w.write(q.text);
55
- w.flush(); //flushしないと, バッファに入るだけで送られていない場合があります.
56
- String result;
85
+ final String text;
57
- do {
58
- //問題を送るとクライアントはそれを表示して入力を待ち, 入力されたら数字を1行として送ってくることにしました.
59
- //なのでそれを待ちます.
60
- String answer = r.readLine(); //行は改行で終わるため, このメソッドが使えます.
61
- if(answer == null) return null; //切断されたらこちらも終わります. 2重ループのため return で一気に抜けます
62
- //答え合わせ.
63
- if (answer.equals(q.correctAnswer)) {
86
+ final String correctAnswer;
87
+ Question(int linecount, String text, String correctAnswer) {
64
- result = "OK";
88
+ this.linecount = linecount;
65
- } else {
66
- result = "NG";
89
+ this.text = text;
90
+ this.correctAnswer = correctAnswer;
67
- }
91
+ }
68
- //結果を一行でクライアントに送ります. クライアントはこれを待っているはずです.
69
- w.write(result + "\n");
70
- w.flush();
71
- } while (result.equals("NG")); //答えが間違っていた場合再び回答待ちになります.
72
- }
73
- w.write("0\n"); //クライアントは次の問題を待っているはずですが, 行数 0 を送って終わりを通知します.
74
- w.flush();
75
-
76
- } catch (IOException e) {
77
- e.printStackTrace();
78
- } finally {
79
- try { s.close(); } catch(IOException ignore) {}
80
- }
81
- return null;
82
- }
83
- //この辺りは仕様やプロトコルによって決めてください.
84
- private class Question {
85
- final int linecount; //text の行数. 出来れば改行の数を数える等で自動で値を求めたい所です
86
- final String text; //問題文
87
- final String correctAnswer; //正解
88
- Question(int linecount, String text, String correctAnswer) {
89
- this.linecount = linecount;
90
- this.text = text;
91
- this.correctAnswer = correctAnswer;
92
- }
93
- }
94
- private Question createQuestion(int questionNumber) {
95
- switch(questionNumber) {
96
- case 1: return new Question(3, //行数
97
- "2019年1月1日は何曜日?\n1=月曜日, 2=火曜日, 3=水曜日\n4=木曜日, 5=金曜日, 6=土曜日\n",
98
- "2"); //正解
99
- case 2: return new Question(1,
100
- "1+2=?\n",
101
- "3");
102
- }
103
- return null; //問題が無くなった.
104
- }
105
92
  }
93
+ private Question createQuestion(int questionNumber) {
94
+ switch(questionNumber) {
95
+ case 1: return new Question(3,
96
+ "2019年1月1日は何曜日?\n1=月曜日, 2=火曜日, 3=水曜日\n4=木曜日, 5=金曜日, 6=土曜日\n",
97
+ "2");
98
+ case 2: return new Question(1,
99
+ "1+2=?\n",
100
+ "3");
101
+ }
102
+ return null;
103
+ }
104
+ }
106
105
  }
107
106
  ```
108
107
  ```java

5

コードに合わせて説明を変更

2019/01/31 13:04

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -2,7 +2,7 @@
2
2
  すいません, 動くものにしようと書いていますが, 一気に書いた状態でまだ動かしていません.
3
3
  レイアウトはクライアント側で, 問題表示TextView id=question, 回答欄EditText id=answer, 判定表示TextView id=result, 回答送信Button id=finalAnswer です. ボタンは全問題終了時のクライアント終了も兼ねています.
4
4
  サーバ側は使っていません.
5
- なるべく説明を入れてみましたが... あくまで参考ということでお願いします.
5
+ 説明を入れてみましたが, 修正すると書き込みが大きすぎになるようで消さざるをえませんでした. あくまで参考ということでお願いします.
6
6
  流れを図にしてみました.
7
7
  ![イメージフロー](a8d65def9178e91c9e95b2881904730b.gif)
8
8
 
@@ -118,18 +118,17 @@
118
118
  questionView = (TextView)findViewById(R.id.question);
119
119
  answerView = (EditText)findViewById(R.id.answer);
120
120
  resultView = (TextView)findViewById(R.id.result);
121
- //回答欄に入力したらボタンを押し, サーバに送信
122
121
  finalAnswer = (Button)findViewById(R.id.finalAnswer);
123
122
  finalAnswer.setOnClickListener(new View.OnClickListener() {
124
123
  @Override
125
124
  public void onClick(View v) {
126
125
  String answer = answerView.getText().toString();
127
- if(answer.length() == 0) return;//入ってなかったら無視
126
+ if(answer.length() == 0) return;
128
127
  new ResultReceiver().execute(answer);
129
128
  }
130
129
  });
131
- manager = new ConnectionManager("10.0.2.2", 8181);//これはエミュレータでの設定(telnet localhost 5554 > redir add tcp:8080:8181 後)
130
+ manager = new ConnectionManager("10.0.2.2", 8181);
132
- new QuestionReceiver().execute();//最初の問題を受信, 表示して回答を待ちます.
131
+ new QuestionReceiver().execute();
133
132
  }
134
133
  private ConnectionManager manager;
135
134
  private class ConnectionManager {
@@ -144,14 +143,14 @@
144
143
  }
145
144
  void connect() throws IOException {
146
145
  if(s == null) {
147
- Log.d("ClientActivity.ConnectionManager.connect", "接続");
146
+ Log.d("ConnectionManager.connect", "接続");
148
147
  s = new Socket(host, port);
149
148
  try {
150
149
  w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
151
150
  r = new BufferedReader(new InputStreamReader(s.getInputStream()));
152
- Log.d("ClientActivity.ConnectionManager.connect", "接続成功");
151
+ Log.d("ConnectionManager.connect", "接続成功");
153
152
  } catch(IOException e) {
154
- Log.e("ClientActivity.ConnectionManager.connect", "接続失敗", e);
153
+ Log.e("ConnectionManager.connect", "接続失敗", e);
155
154
  try { s.close(); } catch(IOException ignore) {}
156
155
  s = null; w = null; r = null;
157
156
  throw e;
@@ -166,37 +165,37 @@
166
165
  @Override
167
166
  protected String doInBackground(Void... aVoid) {
168
167
  try {
169
- Log.d("ClientActivity.QuestionReceiver.doInBackground", "問題受信");
168
+ Log.d("QuestionReceiver.doInBackground", "問題受信");
170
169
  BufferedReader r = manager.getReader();
171
170
  int linecount = Integer.parseInt(r.readLine());
172
- Log.d("ClientActivity.QuestionReceiver.doInBackground", "linecount="+linecount);
171
+ Log.d("QuestionReceiver.doInBackground", "linecount="+linecount);
173
172
  if(linecount == 0) return null;
174
173
  String text = "";
175
174
  for(int i=0; i<linecount; i++) text += r.readLine() + "\n";
176
- Log.d("ClientActivity.QuestionReceiver.doInBackground", "text="+text);
175
+ Log.d("QuestionReceiver.doInBackground", "text="+text);
177
176
  return text;
178
177
  } catch (IOException e) {
179
- Log.e("ClientActivity.QuestionReceiver.doInBackground", "問題受信異常", e);
178
+ Log.e("QuestionReceiver.doInBackground", "問題受信異常", e);
180
179
  e.printStackTrace();
181
180
  }
182
181
  return null;
183
182
  }
184
183
  @Override
185
184
  protected void onPostExecute(String text) {
186
- Log.d("ClientActivity.QuestionReceiver.onPostExecute", "text="+text);
185
+ Log.d("QuestionReceiver.onPostExecute", "text="+text);
187
186
  if(text == null) {
188
187
  finalAnswer.setText("終わります");
189
188
  finalAnswer.setOnClickListener(new View.OnClickListener() {
190
189
  @Override
191
190
  public void onClick(View v) {
192
- Log.d("ClientActivity.QuestionReceiver.onPostExecute", "finalAnswer.OnClick");
191
+ Log.d("QuestionReceiver.onPostExecute", "finalAnswer.OnClick");
193
192
  manager.disconnect();
194
193
  ClientActivity.this.finish();
195
194
  }
196
195
  });
197
196
  return;
198
197
  }
199
- Log.d("ClientActivity.QuestionReceiver.onPostExecute", "問題表示");
198
+ Log.d("QuestionReceiver.onPostExecute", "問題表示");
200
199
  questionView.setText(text);
201
200
  answerView.setText("");
202
201
  resultView.setText("");
@@ -208,30 +207,30 @@
208
207
  protected String doInBackground(String... answers) {
209
208
  String answer = answers[0];
210
209
  try {
211
- Log.d("ClientActivity.ResultReceiver.doInBackground", "回答送信 answer="+answer);
210
+ Log.d("ResultReceiver.doInBackground", "回答送信 answer="+answer);
212
211
  BufferedWriter w = manager.getWriter();
213
212
  w.write(answer + "\n");
214
213
  w.flush();
215
- Log.d("ClientActivity.ResultReceiver.doInBackground", "判定受信");
214
+ Log.d("ResultReceiver.doInBackground", "判定受信");
216
215
  BufferedReader r = manager.getReader();
217
216
  return r.readLine();
218
217
  } catch(IOException e) {
219
- Log.e("ClientActivity.ResultReceiver.doInBackground", "異常", e);
218
+ Log.e("ResultReceiver.doInBackground", "異常", e);
220
219
  e.printStackTrace();
221
220
  }
222
221
  return null;
223
222
  }
224
223
  @Override
225
224
  protected void onPostExecute(String result) {
226
- Log.d("ClientActivity.ResultReceiver.onPostExecute", "判定="+result);
225
+ Log.d("ResultReceiver.onPostExecute", "判定="+result);
227
226
  if(result == null) return;
228
- Log.d("ClientActivity.ResultReceiver.onPostExecute", "判定表示");
227
+ Log.d("ResultReceiver.onPostExecute", "判定表示");
229
228
  resultView.setText(result);
230
229
  if(result.equalsIgnoreCase("OK")) {
231
- Log.d("ClientActivity.ResultReceiver.onPostExecute", "次問題");
230
+ Log.d("ResultReceiver.onPostExecute", "次問題");
232
231
  new QuestionReceiver().execute();
233
232
  } else {
234
- Log.d("ClientActivity.ResultReceiver.onPostExecute", "再回答");
233
+ Log.d("ResultReceiver.onPostExecute", "再回答");
235
234
  answerView.setText("");
236
235
  answerView.requestFocus();
237
236
  }

4

クライアントコード修正

2019/01/31 08:46

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -1,28 +1,12 @@
1
- 普通にクライアント-サーバ型の通信ではどういう感じになるかということで書いてみました.
1
+ 普通にクライアント-サーバではどういう感じになるかということで書いてみました.
2
2
  すいません, 動くものにしようと書いていますが, 一気に書いた状態でまだ動かしていません.
3
3
  レイアウトはクライアント側で, 問題表示TextView id=question, 回答欄EditText id=answer, 判定表示TextView id=result, 回答送信Button id=finalAnswer です. ボタンは全問題終了時のクライアント終了も兼ねています.
4
4
  サーバ側は使っていません.
5
5
  なるべく説明を入れてみましたが... あくまで参考ということでお願いします.
6
-
7
6
  流れを図にしてみました.
8
7
  ![イメージフロー](a8d65def9178e91c9e95b2881904730b.gif)
9
8
 
10
- サーバ側です
11
- ```java(android)
9
+ ```java
12
- package com.example.transqa;
13
-
14
- import android.os.AsyncTask;
15
- import android.support.v7.app.AppCompatActivity;
16
- import android.os.Bundle;
17
-
18
- import java.io.BufferedReader;
19
- import java.io.BufferedWriter;
20
- import java.io.IOException;
21
- import java.io.InputStreamReader;
22
- import java.io.OutputStreamWriter;
23
- import java.net.ServerSocket;
24
- import java.net.Socket;
25
-
26
10
  public class ServerActivity extends AppCompatActivity {
27
11
  @Override
28
12
  protected void onCreate(Bundle savedInstanceState) {
@@ -43,9 +27,9 @@
43
27
  @Override
44
28
  public void run() {
45
29
  try {
46
- while(true) { //延々と受付待ち
30
+ while(true) {//延々と受付待ち
47
- Socket s = ss.accept(); //サーバは受付だけ
31
+ Socket s = ss.accept();//サーバは受付だけ
48
- new Questioner().execute(s); //受付したら, 後は専用スレッドに任せます.
32
+ new Questioner().execute(s);//受付したら, 後は専用スレッドに任せます.
49
33
  }
50
34
  } catch (IOException e) {
51
35
  e.printStackTrace();
@@ -58,7 +42,7 @@
58
42
  private class Questioner extends AsyncTask<Object, Object, String> {
59
43
  @Override
60
44
  protected String doInBackground(Object... objects) {
61
- Socket s = (Socket)objects[0]; //パラメータ1つめは Socket.
45
+ Socket s = (Socket)objects[0];//パラメータ1つめは Socket.
62
46
  try {
63
47
  BufferedWriter w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
64
48
  BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream()));
@@ -121,117 +105,137 @@
121
105
  }
122
106
  }
123
107
  ```
124
- クライアント側です
125
- ```java(android)
108
+ ```java
126
- package com.example.transqa;
127
-
128
- import android.os.AsyncTask;
129
- import android.os.Bundle;
130
- import android.support.v7.app.AppCompatActivity;
131
- import android.view.View;
132
- import android.widget.Button;
133
- import android.widget.EditText;
134
- import android.widget.TextView;
135
-
136
- import java.io.BufferedReader;
137
- import java.io.BufferedWriter;
138
- import java.io.IOException;
139
- import java.io.InputStreamReader;
140
- import java.io.OutputStreamWriter;
141
- import java.net.Socket;
142
-
143
109
  public class ClientActivity extends AppCompatActivity {
110
+ private TextView questionView;
111
+ private EditText answerView;
112
+ private TextView resultView;
113
+ private Button finalAnswer;
114
+ @Override
115
+ protected void onCreate(Bundle savedInstanceState) {
116
+ super.onCreate(savedInstanceState);
117
+ setContentView(R.layout.activity_client);
118
+ questionView = (TextView)findViewById(R.id.question);
119
+ answerView = (EditText)findViewById(R.id.answer);
120
+ resultView = (TextView)findViewById(R.id.result);
121
+ //回答欄に入力したらボタンを押し, サーバに送信
122
+ finalAnswer = (Button)findViewById(R.id.finalAnswer);
123
+ finalAnswer.setOnClickListener(new View.OnClickListener() {
124
+ @Override
125
+ public void onClick(View v) {
126
+ String answer = answerView.getText().toString();
127
+ if(answer.length() == 0) return;//入ってなかったら無視
128
+ new ResultReceiver().execute(answer);
129
+ }
130
+ });
131
+ manager = new ConnectionManager("10.0.2.2", 8181);//これはエミュレータでの設定(telnet localhost 5554 > redir add tcp:8080:8181 後)
132
+ new QuestionReceiver().execute();//最初の問題を受信, 表示して回答を待ちます.
133
+ }
134
+ private ConnectionManager manager;
135
+ private class ConnectionManager {
136
+ private String host;
137
+ private int port;
144
138
  private Socket s;
145
139
  private BufferedWriter w;
146
140
  private BufferedReader r;
147
-
148
- private TextView questionView;
149
- private EditText answerView;
150
- private TextView resultView;
151
- private Button finalAnswer;
152
-
153
- @Override
154
- protected void onCreate(Bundle savedInstanceState) {
141
+ ConnectionManager(String host, int port) {
155
- super.onCreate(savedInstanceState);
156
- setContentView(R.layout.activity_server);
157
-
158
- questionView = (TextView)findViewById(R.id.question);
159
- answerView = (EditText)findViewById(R.id.answer);
160
- resultView = (TextView)findViewById(R.id.result);
161
-
162
- //回答欄に入力したらボタンを押し, サーバに送信
163
- finalAnswer = (Button)findViewById(R.id.finalAnswer);
164
- finalAnswer.setOnClickListener(new View.OnClickListener() {
165
- @Override
166
- public void onClick(View v) {
167
- String answer = answerView.getText().toString();
168
- if(answer.length() == 0) return; //入ってなかったら無視
169
- try {
170
- w.write(answer + "\n"); //サーバに送信
171
- w.flush();
172
- new ResultReceiver().execute(); //結果を別タスクで受ける
173
- //ここでメインも結果を受け取るまで止まりたい所ですが, メインスレッドを止めてはいけません.
174
- //ResultReceiver側でぐるぐる回るプログレスを出しておくのが良いでしょう.
175
- } catch (IOException e) {
176
- e.printStackTrace();
142
+ this.host = host;
143
+ this.port = port;
177
- }
144
+ }
178
- }
145
+ void connect() throws IOException {
179
- });
146
+ if(s == null) {
147
+ Log.d("ClientActivity.ConnectionManager.connect", "接続");
148
+ s = new Socket(host, port);
180
149
  try {
181
- s = new Socket("192.168.1.1", 8080);
182
- w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
150
+ w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
183
- r = new BufferedReader(new InputStreamReader(s.getInputStream()));
151
+ r = new BufferedReader(new InputStreamReader(s.getInputStream()));
184
- setQuestions(); //問題を Socket(実際は BufferedReader) で受け取って表示. 回答待ち
152
+ Log.d("ClientActivity.ConnectionManager.connect", "接続成功");
185
- } catch (IOException e) {
153
+ } catch(IOException e) {
154
+ Log.e("ClientActivity.ConnectionManager.connect", "接続失敗", e);
155
+ try { s.close(); } catch(IOException ignore) {}
186
- e.printStackTrace();
156
+ s = null; w = null; r = null;
157
+ throw e;
187
158
  }
159
+ }
188
160
  }
189
- //falseを返したら問題が無くなり終了です. trueを返したら(次の)問題が表示されたことになります.
190
- private boolean setQuestions() throws IOException {
161
+ BufferedReader getReader() throws IOException { connect(); return r; }
162
+ BufferedWriter getWriter() throws IOException { connect(); return w; }
163
+ void disconnect() { if(s == null) try { s.close(); } catch(IOException ignore) {} }
164
+ }
165
+ private class QuestionReceiver extends AsyncTask<Void,Void,String> {
166
+ @Override
167
+ protected String doInBackground(Void... aVoid) {
168
+ try {
169
+ Log.d("ClientActivity.QuestionReceiver.doInBackground", "問題受信");
191
- //問題文が送られてくるので受け取ります
170
+ BufferedReader r = manager.getReader();
192
- int linecount = Integer.parseInt(r.readLine()); //まず問題文の行数
171
+ int linecount = Integer.parseInt(r.readLine());
172
+ Log.d("ClientActivity.QuestionReceiver.doInBackground", "linecount="+linecount);
193
- if(linecount == 0) return false; //もし行数が 0 だったら問題が無くなったので終了ということにしました.
173
+ if(linecount == 0) return null;
194
174
  String text = "";
195
- for(int i=0; i<linecount; i++) text += r.readLine() + "\n"; //問題文を1行ずつ受け取って改行を付けて繋げます.
175
+ for(int i=0; i<linecount; i++) text += r.readLine() + "\n";
196
- questionView.setText(text); //問題を表示し
197
- answerView.setText(""); //各欄をクリアして
176
+ Log.d("ClientActivity.QuestionReceiver.doInBackground", "text="+text);
198
- resultView.setText("");
199
- answerView.requestFocus(); //回答欄にフォーカスして待ちます.
200
- return true;
177
+ return text;
178
+ } catch (IOException e) {
179
+ Log.e("ClientActivity.QuestionReceiver.doInBackground", "問題受信異常", e);
180
+ e.printStackTrace();
181
+ }
182
+ return null;
201
183
  }
202
- private class ResultReceiver extends AsyncTask<Object,Object,String> {
203
- @Override
184
+ @Override
204
- protected String doInBackground(Object... object) {
185
+ protected void onPostExecute(String text) {
186
+ Log.d("ClientActivity.QuestionReceiver.onPostExecute", "text="+text);
187
+ if(text == null) {
188
+ finalAnswer.setText("終わります");
189
+ finalAnswer.setOnClickListener(new View.OnClickListener() {
205
- try {
190
+ @Override
191
+ public void onClick(View v) {
192
+ Log.d("ClientActivity.QuestionReceiver.onPostExecute", "finalAnswer.OnClick");
206
- return r.readLine();
193
+ manager.disconnect();
207
- } catch(IOException e) {
208
- e.printStackTrace();
194
+ ClientActivity.this.finish();
209
- }
195
+ }
196
+ });
210
- return null;
197
+ return;
211
- }
198
+ }
212
- @Override
213
- protected void onPostExecute(String s) {
199
+ Log.d("ClientActivity.QuestionReceiver.onPostExecute", "問題表示");
214
- if(s == null) return; //通信が切れるとこの条件が一致してしまいます. その場合どうしましょう.
215
- resultView.setText(s);
200
+ questionView.setText(text);
216
- if(s.equalsIgnoreCase("OK")) { //正解だったら
217
- try {
218
- if(!setQuestions()) { //次の問題を受信・表示します. が, 問題が無くなったら終わります
219
- finalAnswer.setText("終わります");
201
+ answerView.setText("");
220
- finalAnswer.setOnClickListener(new View.OnClickListener() {
221
- @Override
222
- public void onClick(View v) {
223
- ClientActivity.this.finish(); //かなり強引です!
224
- }
225
- });
226
- }
227
- } catch (IOException e) {
228
- e.printStackTrace();
229
- }
230
- } else { //不正解だったら
231
- answerView.setText(""); //回答欄をクリアして
202
+ resultView.setText("");
232
- answerView.requestFocus(); //もう一度回答欄にフォーカスして待ちます.
203
+ answerView.requestFocus();
233
- }
234
- }
235
204
  }
205
+ }
206
+ private class ResultReceiver extends AsyncTask<String,Object,String> {
207
+ @Override
208
+ protected String doInBackground(String... answers) {
209
+ String answer = answers[0];
210
+ try {
211
+ Log.d("ClientActivity.ResultReceiver.doInBackground", "回答送信 answer="+answer);
212
+ BufferedWriter w = manager.getWriter();
213
+ w.write(answer + "\n");
214
+ w.flush();
215
+ Log.d("ClientActivity.ResultReceiver.doInBackground", "判定受信");
216
+ BufferedReader r = manager.getReader();
217
+ return r.readLine();
218
+ } catch(IOException e) {
219
+ Log.e("ClientActivity.ResultReceiver.doInBackground", "異常", e);
220
+ e.printStackTrace();
221
+ }
222
+ return null;
223
+ }
224
+ @Override
225
+ protected void onPostExecute(String result) {
226
+ Log.d("ClientActivity.ResultReceiver.onPostExecute", "判定="+result);
227
+ if(result == null) return;
228
+ Log.d("ClientActivity.ResultReceiver.onPostExecute", "判定表示");
229
+ resultView.setText(result);
230
+ if(result.equalsIgnoreCase("OK")) {
231
+ Log.d("ClientActivity.ResultReceiver.onPostExecute", "次問題");
232
+ new QuestionReceiver().execute();
233
+ } else {
234
+ Log.d("ClientActivity.ResultReceiver.onPostExecute", "再回答");
235
+ answerView.setText("");
236
+ answerView.requestFocus();
237
+ }
238
+ }
239
+ }
236
240
  }
237
241
  ```

3

スレッド開始メソッド間違い

2019/01/31 03:42

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -29,7 +29,7 @@
29
29
  super.onCreate(savedInstanceState);
30
30
  setContentView(R.layout.activity_server);
31
31
  try {
32
- new Thread(new Server(8080)).run();
32
+ new Thread(new Server(8080)).start();
33
33
  } catch (IOException e) {
34
34
  e.printStackTrace();
35
35
  }

2

イメージフロー図追加

2019/01/30 14:54

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -4,6 +4,9 @@
4
4
  サーバ側は使っていません.
5
5
  なるべく説明を入れてみましたが... あくまで参考ということでお願いします.
6
6
 
7
+ 流れを図にしてみました.
8
+ ![イメージフロー](a8d65def9178e91c9e95b2881904730b.gif)
9
+
7
10
  サーバ側です
8
11
  ```java(android)
9
12
  package com.example.transqa;

1

誤字

2019/01/30 11:17

投稿

jimbe
jimbe

スコア13355

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  普通にクライアント-サーバ型の通信ではどういう感じになるかということで書いてみました.
2
2
  すいません, 動くものにしようと書いていますが, 一気に書いた状態でまだ動かしていません.
3
- レイアウトはクライアント側で, 問題表示TextView id=question, 回答欄EditView id=answer, 判定表示TextView id=result, 回答送信Button id=finalAnswer です. ボタンは全問題終了時のクライアント終了も兼ねています.
3
+ レイアウトはクライアント側で, 問題表示TextView id=question, 回答欄EditText id=answer, 判定表示TextView id=result, 回答送信Button id=finalAnswer です. ボタンは全問題終了時のクライアント終了も兼ねています.
4
4
  サーバ側は使っていません.
5
5
  なるべく説明を入れてみましたが... あくまで参考ということでお願いします.
6
6