[Android] Connecting Android App to Web Server
Updated:
기본 설정(안드로이드)
- Manifest 인터넷 권한 설정
- Manifest application 태그에 CleartextTraffic 사용 추가(HTTP 접근 위함)
<application
<!-- ... -->
android:usesCleartextTraffic="true">
- build.gradle(Module: app)에 의존성 추가(live data 쓰기 위함)
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- MainActivity onCreate에서 thread 분리
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Java 서버(Eclipse에서)
web_and라는 이름의 Dynamic Web Project 생성
andtest라는 패키지를 만들고 login이라는 Servlet을 만들었다.
- doGet에 이렇게 코드를 썼다.
- 목적: id가 ‘aaa’고 pwd가 ‘111’일 때만 ‘로그인 성공’을 띄운다.
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
String id = request.getParameter("id");
String pwd = request.getParameter("pwd");
boolean flag = false;
if (id.equals("aaa") && pwd.equals("111")) {
flag = true;
}
request.setAttribute("flag", flag);
RequestDispatcher rd = request.getRequestDispatcher("views/login.jsp");
rd.forward(request, response);
}
프로젝트의 WebContent 폴더에 views라는 폴더를 만들고
views 안에 login.jsp 파일을 만들었다.
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
{"flag":${flag}}
웹서버 실행하면 처음엔 ‘localhost:7878/web_and/’로 404 에러가 뜬다. (7878은 내가 톰캣 설치할 때 지정한 포트주소)
주소 뒤에 ‘login?id=aaa&pwd=111’ 추가하고 이동하면 flag가 true인 채로 나타난다.
반면, aaa과 111 이외의 인수를 넣으면 flag가 false로 나타나게 된다.
안드로이드
1. MainActivity
레이아웃
- login Button: onClick 메서드 이름은 onLogin
버튼 핸들러
public void onLogin(View view) {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}
2. WebViewModel 클래스
public class WebViewModel extends ViewModel {
private MutableLiveData<String> res;
private ExecutorService executorService;
private RequestHttpURLConnection conn;
public void setRes(MutableLiveData<String> res) {
this.res = res;
}
public WebViewModel() {
executorService = Executors.newSingleThreadExecutor();
conn = new RequestHttpURLConnection();
}
public void req(String url, ContentValues cv) {
String r = conn.request(url, cv);
res.postValue(r);
}
}
3. RequestHttpURLConnection 클래스
public class RequestHttpURLConnection {
public String request(String _url, ContentValues _params) {
// HttpURLConnection 참조 변수.
HttpURLConnection urlConn = null;
// URL 뒤에 붙여서 보낼 파라미터.
StringBuffer sbParams = new StringBuffer();
/**
* 1. StringBuffer에 파라미터 연결
* */
// 보낼 데이터가 없으면 파라미터를 비운다.
if (_params == null)
sbParams.append("");
// 보낼 데이터가 있으면 파라미터를 채운다.
else {
// 파라미터가 2개 이상이면 파라미터 연결에 &가 필요하므로 스위칭할 변수 생성.
boolean isAnd = false;
// 파라미터 키와 값.
String key;
String value;
for (Map.Entry<String, Object> parameter : _params.valueSet()) {
key = parameter.getKey();
value = parameter.getValue().toString();
// 파라미터가 두개 이상일때, 파라미터 사이에 &를 붙인다.
if (isAnd)
sbParams.append("&");
sbParams.append(key).append("=").append(value);
// 파라미터가 2개 이상이면 isAnd를 true로 바꾸고 다음 루프부터 &를 붙인다.
if (!isAnd)
if (_params.size() >= 2)
isAnd = true;
}
}
/**
* 2. HttpURLConnection을 통해 web의 데이터를 가져온다.
* */
try {
URL url = new URL(_url);
urlConn = (HttpURLConnection) url.openConnection();
// [2-1]. urlConn 설정.
urlConn.setRequestMethod("POST"); // URL 요청에 대한 메소드 설정 : POST.
urlConn.setRequestProperty("Accept-Charset", "UTF-8"); // Accept-Charset 설정.
urlConn.setRequestProperty("Context_Type", "application/x-www-form-urlencoded;charset=UTF-8");
// [2-2]. parameter 전달 및 데이터 읽어오기.
String strParams = sbParams.toString(); //sbParams에 정리한 파라미터들을 스트링으로 저장. 예)id=id1&pw=123;
OutputStream os = urlConn.getOutputStream();
os.write(strParams.getBytes("UTF-8")); // 출력 스트림에 출력.
os.flush(); // 출력 스트림을 플러시(비운다)하고 버퍼링 된 모든 출력 바이트를 강제 실행.
os.close(); // 출력 스트림을 닫고 모든 시스템 자원을 해제.
System.out.println("param:" + strParams);
// [2-3]. 연결 요청 확인.
// 실패 시 null을 리턴하고 메서드를 종료.
if (urlConn.getResponseCode() != HttpURLConnection.HTTP_OK) {
System.out.println("연결실패");
return null;
}
// [2-4]. 읽어온 결과물 리턴.
// 요청한 URL의 출력물을 BufferedReader로 받는다.
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8"));
// 출력물의 라인과 그 합에 대한 변수.
String line;
String page = "";
// 라인을 받아와 합친다.
while ((line = reader.readLine()) != null) {
page += line;
}
System.out.println("result:" + page);
return page;
} catch (MalformedURLException e) { // for URL.
e.printStackTrace();
} catch (IOException e) { // for openConnection().
e.printStackTrace();
} finally {
if (urlConn != null)
urlConn.disconnect();
}
return null;
}
}
4. LoginActivity
레이아웃
- 아이디 입력칸
- 비밀번호 입력칸
- 로그인 버튼
액티비티
public class LoginActivity extends AppCompatActivity {
private EditText editId;
private EditText editPwd;
private WebViewModel model;
private MutableLiveData<String> res;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
editId = findViewById(R.id.editId);
editPwd = findViewById(R.id.editPwd);
res = new MutableLiveData<>();
model = new ViewModelProvider(this).get(WebViewModel.class);
model.setRes(res);
res.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
String str = "";
try {
JSONObject obj = new JSONObject(s);
if (obj.getBoolean("flag")) {
str = "로그인 성공";
} else {
str = "로그인 실패";
}
Toast.makeText(LoginActivity.this, str, Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
public void onLogin(View view) {
String id = editId.getText().toString();
String pwd = editPwd.getText().toString();
ContentValues cv = new ContentValues();
cv.put("id", id);
cv.put("pwd", pwd);
model.req("https://서버IP주소:포트주소/web_and/login", cv);
id_et.setText("");
pwd_et.setText("");
}
}
Leave a comment