반응형

가급적 테스트 용도로만 사용하세요.


MSSQL 서버에 직접 연결하여 데이터를 주고 받으면 

암호화안된 데이터 노출될 수 도 있고..


앱에서 소스코드를 추출하여 MSSQL 서버의 비밀번호가 노출될 수 있습니다.




API21을 사용하도록 새로운 안드로이드 프로젝트를 생성하고

생성된 디렉토리의 libs라는 하위 디렉토리에 jtds-1.2.8.jar를 복사해 넣었습니다.

 


왼쪽에 있는 Android를 클릭해서 Project로 바꾸고.. app하위에 있는 libs에서 jtds-1.2.8.jar를 선택하고 마우스 우클릭해서 나오는 메뉴에서 Add a Library를 선택합니다.(캡처는 1.3.1을 사용할떄 인데 문제가 있어서 1.2.8로 바꾸었습니다.)


http://sourceforge.net/projects/jtds/files/jtds/1.2.8/ 에서 jtds-1.2.8.jar가 포함된 압축파일을 다운로드 받을 수 있습니다.



 

이제 DB를 출력하기 위해 사용하게 될 listview를 사용하는 레이아웃을 생성합니다.

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"  
  3.     android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"  
  4.     android:paddingRight="@dimen/activity_horizontal_margin"  
  5.     android:paddingTop="@dimen/activity_vertical_margin"  
  6.     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">  
  7.     
  8.     <ListView  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:id="@+id/listView" />  
  12. </RelativeLayout>  

 


그리고 AndroidManifest.xml 파일에 아래 한 줄을 추가해줍니다.

<uses-permission android:name="android.permission.INTERNET" />

 

 

 


그리고 다음과 같은 소스코드를 사용하면 원하는 결과를 얻을 수 있습니다. 5.0(API21)에서 정상적으로 동작하는 것을 확인했습니다.

버전에 따라 동작을 안하거나 문제가 발생할 수 있습니다.

  1. package com.tistory.webnautes.mssqltest;  
  2.     
  3. import android.app.Activity;  
  4. import android.os.AsyncTask;  
  5. import android.os.Build;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.util.Log;  
  10. import android.widget.ArrayAdapter;  
  11. import android.widget.ListView;  
  12. import java.sql.Connection;  
  13. import java.sql.DriverManager;  
  14. import java.sql.ResultSet;  
  15. import java.sql.Statement;  
  16. import java.util.ArrayList;  
  17.     
  18. public class MainActivity extends Activity {  
  19.     ListView listview;  
  20.     ArrayAdapter<String> adapter;  
  21.     MyAsyncTask mTask;  
  22.     static String query = "select * from state order by curdate desc " ;  
  23.     
  24.     @Override  
  25.     protected void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.activity_main);  
  28.     
  29.         listview = (ListView)findViewById(R.id.listView);  
  30.         adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);  
  31.         listview.setAdapter(adapter);  
  32.     }  
  33.     
  34.     @Override  
  35.     protected void onStart() {  
  36.         super.onStart();  
  37.     
  38.         handler.sendEmptyMessage(0);  
  39.     }  
  40.     
  41.     
  42.     class MyAsyncTask extends AsyncTask<String, Void, ArrayList<String>>  
  43.     {  
  44.     
  45.         @Override  
  46.         protected void onPreExecute(){  
  47.             super.onPreExecute();  
  48.         }  
  49.     
  50.     
  51.         @Override  
  52.         protected ArrayList<String> doInBackground( String... params){  
  53.     
  54.     
  55.             ArrayList<String> list = new ArrayList<String>();  
  56.     
  57.     
  58.     
  59.             ResultSet reset = null;  
  60.             Connection conn = null;  
  61.     
  62.     
  63.     
  64.             try {  
  65.                  Class.forName("net.sourceforge.jtds.jdbc.Driver");  
  66.                 conn = DriverManager.getConnection("jdbc:jtds:sqlserver://DB버주소;databaseName=DB","이디","스워드");  
  67.                 Statement stmt = conn.createStatement();  
  68.     
  69.                 reset = stmt.executeQuery(query);  
  70.     
  71.     
  72.     
  73.                 while(reset.next()){  
  74.     
  75.                     if ( isCancelled() ) break;  
  76.     
  77.                     final String str = reset.getString(1)+" "+reset.getString(3)+" "+reset.getString(4);  
  78.                     list.add(str);  
  79.     
  80.     
  81.                 }  
  82.                 conn.close();  
  83.             }  
  84.     
  85.             catch (Exception e)  
  86.             {  
  87.                 Log.w("111Error connection""" + e.getMessage());  
  88.             }  
  89.     
  90.             return list;  
  91.         }  
  92.     
  93.         @Override  
  94.         protected void onPostExecute(ArrayList<String> list){  
  95.     
  96.             adapter.clear();  
  97.             adapter.addAll(list);  
  98.     
  99.     
  100.             adapter.notifyDataSetChanged();  
  101.             handler.sendEmptyMessageDelayed(01000);  
  102.     
  103.         }  
  104.     
  105.         @Override  
  106.         protected void onCancelled(){  
  107.             super.onCancelled();  
  108.         }  
  109.     }  
  110.     
  111.     public Handler handler = new Handler(){  
  112.         public void handleMessage( Message msg){  
  113.             super.handleMessage(msg);  
  114.     
  115.             mTask = new MyAsyncTask();  
  116.     
  117.             mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");  
  118.         }  
  119.     };  
  120. }  

 

 


다음은 실행결과입니다. 1초마다 DB데이터를 다시 가져와서 뿌리도록 한 결과입니다.

반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. Joel 2015.10.08 15:21

    리스트를 불러오는건 성공했습니다.
    혹시 데이터를 업데이트 하는 방법은 없을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2015.10.08 15:40 신고

      업데이트 되지 않나요????
      제가 작성한 앱에서는 시계가 계속 업데이트 되고 있습니다..

  2. Joel 2015.10.08 16:44

    1초마다 업데이트 되는거 말구 버튼 하나 생성해서 쿼리문을 날릴까합니다
    내용은 update dbtest set nu='0' where no=2 이런식으로요
    그래서 업데이트 된 내용을 다시 뿌려 주는거죠

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2015.10.08 17:13 신고

      handler.sendEmptyMessageDelayed(0, 1000); 부분 삭제하고...

      아래 두줄을 버튼 클릭시 실행하면 되지 않을까요?
      mTask = new MyAsyncTask();
      mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "");

  3. JS 2015.11.04 15:37

    DB도 연결이 잘 된것같고 ResultSet에 컬럼 네임들도 잘 들어왔는데
    정작 안에 rowData가 하나도 안넘어옵니다 ㅠㅠ
    쿼리문도 select from 만 쓴 간단한 쿼리문인데

  4. Hide 2015.11.17 14:38

    이 방법으로 하면 만들어진 어플을 리버싱 할 경우
    db접속정보랑 아이디 비번 다 노출되지 않을까요?
    보안상 위험할거 같네요.

  5. 2016.06.04 18:08

    비밀댓글입니다

  6. chobo 2016.06.14 18:43

    드라이버를 로딩하는 부분
    Class.forName("net.sourceforge.jtds.jdbc.Driver");
    conn = DriverManager.getConnection("jdbc:jtds:sqlserver://DB서버주소;databaseName=DB이름","아이디","패스워드");

    어떻게 채워 넣어야 하나요? 예제마다 조금씩 다르던데..
    맞다고 생각한대로 해도 리스트를 보여주지 않네요 ㅠㅠ.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.06.14 19:23 신고

      conn = DriverManager.getConnection("jdbc:jtds:sqlserver://DB서버주소;databaseName=DB이름","아이디","패스워드");

      DB서버주소
      DB이름
      아이디
      패스워드
      를 각각 위치에 넣어주시면 됩니다..

  7. thankyou 2016.08.01 15:07

    우선 도움 많이 되고있어서 감사드립니다!
    하나 여쭤볼께 있는데요.
    "select * from state order by curdate desc " 에서 바꿀 부분이 있는건가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.08.01 15:09 신고

      무슨 문제라도 있나요?

    • thankyou 2016.08.01 15:23

      실행시키면 그냥 빈화면만 뜨네요..
      혹시 저부분을 바꿔야 하는건가해서 여쭤봤습니다.
      제가 다른 부분에서 실수한걸까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.08.01 15:28 신고

      select * from 테이블명

      이렇겐.바꾸어 보세요

    • thankyou 2016.08.01 15:42

      그래도 안되네요.. 제가 소스를 보다보니까
      DB 서버주소를 잘못입력한거 같기도한데
      DB 서버주소 확인 하는방법좀 알려주실수 있으신가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2016.08.01 15:50 신고

      이 툴로 확인해보세요

      http://h5bak.tistory.com/m/post/277

    • thankyou 2016.08.01 16:04

      네 한번 해볼께요.
      답변도 빨리해주시고 감사합니다!

  8. sql 2017.05.12 20:24

    "select * from state order by curdate desc " 에서 조건(where)을 EditText 에 입력된 값으로 하고
    버튼을 눌렀을때 조회 되게 할 수 없을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.12 21:45 신고

      버튼 클릭시 query 스트링에 where 절을 추가하여 질의하도록 수정해야 합니다.

      AsyncTask 실행시킬때 스트링을 넘겨주시면 됩니다.

  9. 질문자 2017.05.15 09:25

    혹시 select절에
    select * 밖에 못쓰나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.15 13:32 신고

      select 다음에 *대신에 특정 필드 이름을 적을 수 있습니다..

      SELECT field1, field2 FROM table;

  10. 질문자 2017.05.15 16:25

    네 아까 해보니까 되요! 감사합니다
    그런데 리스트 띄우고나서 클릭했을때 클릭이벤트처리 하고 싶은데
    이벤트처리 리스너는 oncreate에 있고
    리스트는 MyAsyncTask여기에 있는데
    어떻게 처리를 해야 할까요

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.15 18:22 신고

      아래 글을 참고해보세요.

      https://medium.com/@henen/빠르게-배우는-안드로이드-리스트뷰-listview-4-클릭이벤트-onitemclicklistener-toast-4432e650cb

  11. sese 2017.05.23 09:49

    다른 컴퓨터에서 구축한 웹서버 DB 접근하려면 이 예제말고 php Mysql 예제 쓰신걸로 따라해야 하는건가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.24 03:47 신고

      이 예제에는 MSSQL와 직접 연결하여 데이터를 읽어오는 것만 구현되어 있지만..
      반대로 저장하는 것도 가능합니다...

      하지만 이렇게 연결하면 보안 문제가 있어서 ..

      보통은 "Android PHP MySQL 예제" 처럼 서버에 있는 웹언어를 거치게 한다든가...

      아니면 MSSQL과 통신하는 프로그램을 서버쪽에 따로 만들어서 TCP/IP 통신으로 안드로이드에서 간접적으로 접근합니다.

  12. llt911 2017.05.23 16:23

    Statement stmt = conn.createStatement(); 이쪽이 에러가 나는데 왜그럴까요 ㅜㅜ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.24 03:50 신고

      우선 다른 데이터베이스 뷰어로 MSSQL 서버에 접속이 가능한지 테스트해보고
      이상 없으면 ...


      안드로이드 코드의 다음줄에 있는 MSSQL 접속 정보를 확인해봐야 할듯합니다.

      DriverManager.getConnection("jdbc:jtds:sqlserver://DB서버주소;databaseName=DB이름","아이디","패스워드");

  13. sese 2017.05.24 11:27

    번거롭게 해드려서 죄송한데 한가지 더 질문드립니다.
    아까 위에서 답하신거에서 만약 보안 신경안쓴다면 그냥
    이 예제대로 코드에 다른컴 아이피넣고 db 계정이랑 비번 넣고 접속해서 불러 올 수 있는건가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2017.05.24 11:30 신고

      보안 신경안쓰면 사용할 수 있는 방법입니다..

      오래전 포스팅이라 진행하다가 문제가 발생할 수도 있습니다.

  14. Hiding 2019.05.06 13:26

    안녕하세요.

    포스트가 개발에 많은 도움이 되었습니다.

    한가지 질문이 있습니다.

    에뮬레이터에서는 정상적으로 DB데이터 처리가 가능한데 스마트폰 디버깅시 (WIFI 동일 환경) DriverManager.getConnection 부분에서

    Suspend가 걸리는거 같습니다.

    혹시 제가 무었인가를 놓치고 있을까요?

    답변달아 주시면 정말 감사 할것 같습니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.06 18:56 신고

      다음 글을 참고해보세요.

      https://stackoverflow.com/a/23868456

  15. narisca 2019.07.24 17:32

    안녕하세요
    정말 많은 도움이 되었습니다..
    임시데이타베이스에 2개행 짜리 만들어서 테스트를 해봤는데
    테이블이 달라서 그런건지
    디비에 추가해놓은 데이터확인은 되는데
    저는 데이타베이스쪽에는 입력되는게 없습니다
    시계가 업데이트 된다고하셨는데
    입력부분이 어디인지.. 알수있을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.07.24 18:20 신고

      데이터베이스에서 가져올때 보이는 시계는 디바이스에서 1초마다 데이터베이스에 입력해주는 거였습니다..

      따로 프로그램을 짜서 데이터베이스에 일정 시간마다 데이터를 넣어주도록 하고 테스트하면 좋을듯 싶습니다.

    • narisca 2019.07.25 15:16

      안녕하세요
      답변정말 감사드립니다.
      선생님이 하신 코드 그대로도 해보았는데
      테이블네임 서버접속코드는 바꿨구요
      처음엔 curdate를 알수없다고 나와서
      order by curdate desc 이부분을 지우고
      했더니 DB에있는 내용을 얻어오긴했습니다. 하지만 예제처럼 시간값을 얻어오거나
      데이터베이스에 데이터가 1초마다 업데이트되진않는데
      어떤문젠지 알수있을까요..

    • narisca 2019.07.25 15:58

      current_date() 라고 하면 근처구문이 잘못되었다고 나오네요
      쿼리문을 변경해야하는건가요?

    • narisca 2019.07.25 17:51

      마지막으로 제가 디바이스 연결해서 돌려보려고 하니 작동이 안되더라구요..
      구글링해보니 안드로이드와 외부DB는
      연결이 안된다고 나와있는데
      이 예제는 로컬서버 이용하신건가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.07.25 17:59 신고

      여러대의 디바이스에서 현재 시간을 디비에 넣어주도록 했었습니다.


      state 테이블에 있는 모든 레코드를 가져오는데 curdate 필드 기준으로 정렬을 하는 겁니다.

      select * from state order by curdate desc

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.07.25 18:20 신고

      데이터베이스 서버는 데어터센터에 있는 서버를 사용했었습니다.

    • narisca 2019.07.26 09:36

      답변 감사드립니다
      유튜브 구독하겠습니다!

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.07.26 12:10 신고

      감사합니다 :)

  16. 2019.07.31 13:19

    비밀댓글입니다

  17. ILLHYHL 2020.06.17 10:43

    W/111Error connection: Network error IOException: failed to connect to /127.0.0.1 (port 1433) from /:: (port 38668): connect failed: ECONNREFUSED (Connection refused)

    에러가 계속 발생해서 한시간동안 찾다가 찾지 못해서 이렇게 문의합니다 ...

  18. BlogIcon 초보자 2020.06.17 21:32

    안녕하세요!! 작성자님 덕에 많이 성장한 초보자입니다 ㅎㅎ 한 번 더 도움이 필요해서 글 남기게 되었습니다

    제가 review기능을 작성하였는데, 텍스트만 있는 리뷰는 입출력 모두 잘 됩니다. 여기에 추가적으로 사진리뷰기능을 넣으려고 기존 DB에 사진데이터를 BLOB형식으로 추가하여 올렸습니다. 올리는거까진 어떻게 성공을 하였는데 받아와서 앱에 출력하는 부분이 도무지 해결이 안되어 질문남겨봅니다..ㅠ

    protected void onPostExecute(String result) {
    super.onPostExecute(result);

    progressDialog.dismiss();
    mTextViewResult.setText(result);
    Log.d(TAG, "response - " + result);

    if (result == null) {

    mTextViewResult.setText(errorString);
    } else {

    mJsonString = result;
    showResult();
    }
    }

    요 코드에서 log.d부분부터 실행이 아에 안되는것 처럼 보이더라구요. result 인자는 제대로 들어왔었는데 딱 저기부터 로그캣도 안뜨고 아에 아무것도 불러오지 않으며 연결이 끊긴것처럼 작동합니다. 혹시 기존 string 데이터가 아닌 저런 BLOB데이터는 다르게 작성해야하나요? 혹시 참고할만한 예가 있을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.06.17 21:59 신고

      해본 부분이 아니라서.. 답변하기가 힘드네요.

      본 포스트에 댓글을 다신거 봐서는 mssql을 사용하시는 듯한데 맞나요.

      구글에서 다음 처럼 검색해서 필요한 글을 찾아야할 듯합니다.

      blob mssql image android

    • 초보자 2020.06.17 23:27

      답변 감사합니다! BLOB로 저장했더니 아주 길어져서 log.d부분을 아에 제거하고 하니까 뒤쪽도 돌아가더라구요 ㅎㅎ 다른 문제가 발생했지만요...ㅠㅠ 답변 정말 감사드립니다!!

  19. 손님 2020.06.27 17:49

    안녕하세요 데이터베이스에 들어있는 데이터가 넘어오는건 성공했습니다.
    헌데 2개의 열 값만 출력되던데 혹시 원하는 특정 열이나 모든열이 출력되게끔 할수는 없나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.06.27 20:02 신고

      아래 부분에 보이길 원하는 열을 추가하면 됩니다.

      final String str = reset.getString(1)+" "+reset.getString(3)+" "+reset.getString(4);

+ Recent posts