리스트를 이용하여 for문을 돌리다가 리스트내의 요소를 제거하려고 할때 발생하는 에러

꼭 제거를 해야 하면 for문 밖에서 처리해야 한다.

안드로이드에서는 기본적으로 JSON을 지원해주지만 Java에서 JSON을 사용할 경우 아래와 같은 라이브러리 중 하나를 추가해야 사용할 수 있다.

JSON.simple ( Yidong Fang )

GSON ( Google )

Jackson ( FasterXML )

JSONP  ( Oracle )


해외 사이트에서 JSON라이브러리들을 벤치마킹한 결과를 봤을 때

쿼리문의 길이에 상관없이 2순위를 유지하는 JSON.simple을 사용하였다.


json-simple 라이브러리 다운받는 곳

https://code.google.com/archive/p/json-simple/


String 타입인 strJSON에 있는 JSON데이터를 가져와서 사용하는 방법. get의 반환값이 Object 타입이라 형변환을 해야한다.

 

1
2
JSONObject job = (JSONObject)JSONValue.parse(strJSON);
String id = (String)job.get("ID"),pass=(String)job.get("Pass");
cs


데이터를 넣는 방법은 put메소드를 사용하여 넣는다.

 

1
2
3
JSONObject job = new JSONObject();
job.put("ID","Admin");
job.put("Pass","Hello");
cs


Java와 Oracle을 연동하기 위해선 JDBC를 사용해야 한다.

JDBC는 오라클을 설치하고 나면 아래 경로에서 가져올 수 있다.

오라클이 설치된 곳\product\11.2.0\dbhome_1\jdbc\lib

프로젝트에 JDBC 라이브러리를 추가한 후 사용하면 된다.


자바로 드라이브 불러오기 - 실제로 라이브러리를 불러오는 동작

 

1
Class.forName("oracle.jdbc.driver.OracleDriver");
cs

 


자바에서 오라클DB 접속 url에서 'jdbc:oracle:thin:데이터베이스가있는 ip:데이터베이스의 포트번호:데이터베이스 SID


1
2
url="jdbc:oracle:thin:@localhost:1521:oracle";
conn = DriverManager.getConnection(url,id,pw); 
cs

 

 

자바에서 오라클로 쿼리를 날릴때 사용 - Statement, PreparedStatement 클래스

쿼리를 날릴 때 Insert, Delete, Update 와 같은 데이터 수정은 executeUpdate() 메소드를 사용하고, Selete와 같은 데이터 검색은 executeQuery() 메소드를 사용하여 결과를 ResultSet으로 리턴받아 검색 결과를 받을 수 있음

Statement는 해당 쿼리를 만드는데 들어가는 유동적인 값을 일일히 +연산자를 통해 연결해서 넣어줘야하지만

PreparedStatement를 사용하면 쿼리문에 들어갈 값을 '?'로 처리한뒤 setXXX(String, Int 등) 메소드를 통해 쉽게 넣을 수 있다.


Statement 클래스 사용시

1
2
3
4
5
6
7
Statement stat = conn.createStatement();        
ResultSet rs = stat.executeQuery("select count(*) from USER_TABLE 
          where USER_ID = '"+"admin"+"' and USER_PW = '"+"admin"+"'");
while(rs.next()){
    String result = rs.getString(1);
    System.out.println(result);
}
cs
PreparedStatement 사용시

1
2
3
4
5
PreparedStatement pstmt = null;
final String sql = "select * from lab_client_table where userid = ?";
pstmt= conn.prepareStatement(sql);
pstmt.setString(1, userid);
ResultSet rs = pstmt.executeQuery();
cs

 

사용이 끝나면 close해서 자원회수를 한다.

 

1
2
3
rs.close();
stat.close();
conn.close();
cs


사용 버전 : API 19

사용 도구 : Android Studio 1.3.1


1. Sub Thread의 생성자 매개변수로 변경할 위젯을 받아 저장한뒤 Post로 수정

  -> 실코딩에선 부적합


2. Interface를 이용한 Callback 메소드로 수정

  -> 단일 처리밖에 안됨

1
2
3
4
5
6
7
8
9
10
11
    private ProcessCallback m_Callback = new ProcessCallback() {
        @Override
        public void callback(final String result) {
            tvResult.post(new Runnable() {
                @Override
                public void run() {
                    tvResult.setText(result);
                }
            });
        }
    };
cs

▲MainActivity.java

MainActivity에 Interface인 ProcessCallback 객체를 생성후 callback 메소드를 구현한다.

1번 방법을 사용할 경우 위에서 post 메소드만 때서 Sub Thread의 run에 넣어주면 된다.


1
2
3
4
5
6
7
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ProcessThread thread = new ProcessThread(m_Callback);
                thread.start();
            }
        });
cs

▲MainActivity.java

btn1를 클릭하면 Thread를 상속받은 ProcessThread 객체를 생성할때 m_CallBack을 넘겨주고 Thread 시작


1
2
3
4
5
6
7
8
9
10
11
    @Override
    public void run() {
        StringBuffer result = new StringBuffer();
        try {
            sleep(5000);
            result.append("Process Result");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        m_Callback.callback(result.toString());
    }
cs

▲ProcessThread.java

callback 메소드로 UI 수정


3. Handler를 이용한 UI 수정 

  -> 다중처리 가능


1
2
3
4
5
6
7
8
9
10
11
12
13
    private Handler m_Handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == 0) {
                String data = msg.getData().getString("result");
                tvResult.setText(data);
            }
            else if( msg.what == 1)
            {
 
            }
        }
    };
cs

▲MainActivity.java

MainActivity에 Handler 객체를 생성, 이 Handler는 Main Thread에서 동작한다.

1
2
3
4
5
6
7
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ProcessThread2 thread = new ProcessThread2(m_Handler);
                thread.start();
            }
        });
cs

btn2를 클릭시 ProcessThread2 객체를 생성하고 실행한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @Override
    public void run() {
        StringBuffer result = new StringBuffer();
        try {
            sleep(5000);
            result.append("Process Result");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Message message = new Message();
 
        Bundle bundle = new Bundle();
        bundle.putString("result", result.toString());
        message.setData(bundle);
 
        message.what = MainActivity.REUSLT_OK;
        message.setTarget(m_Handler);
        message.sendToTarget();
 
    }
cs

▲ProcessThread2.java

보낼 Message를 생성하고 보낸다.(데이터를 넣기 위해서 Bundle을 생성하여 데이터를 넣는다.)


AndroidThreadTest.zip


사용 버전 : API 19

사용 도구 : Android Studio 1.3


어플 내에 test.json 파일을 불러 'Read'시 day, Subject, Duration 값을 받아 출력

'Add'시 빈칸을 확인한 후 JSONObject로 만든 후 JSONArray에 넣고 파일 덮어쓰기


읽는 순서 JSONArray -> JSONObject -> getString 또는 getInt 메소드로 값 받기

쓰는 순서 JSONObject 객체 생성 -> put으로 Object에 넣기 -> JSONArray에 put으로 넣기

사용 예외 JSONException


JSONTest.zip


아래와 같이 평범하게 스크롤 뷰안에 리스트뷰를 넣으려고하면 match_parent로 설정했음에도 불구하고 꽉 차지 않는다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <ListView
            android:id="@+id/lvSocketList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:drawSelectorOnTop="false">
        </ListView>
    </ScrollView>
</LinearLayout>
 
cs





이 문제를 해결하는 방법은 많지만 간단한 방법은 ScrollView의 속성인 fillViewport을 true로 설정하면 꽉채우게 된다.



 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">
        <ListView
            android:id="@+id/lvSocketList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:drawSelectorOnTop="false">
        </ListView>
    </ScrollView>
</LinearLayout>
 
cs






한컴퓨터에서 서버와 클라이언트를 켜서 통신하는것과 외부 인터넷을 잡은 컴퓨터에서 서버에 접속하는 프로그램

<id>를 입력하고 뒤에 문자열을 적으면 해당 클라이언트의 아이디가 된다.


▲왼)서버 오)클라이언트  한컴퓨터에서 동시에 돌리는 영상 + 38초 쯤에 다른 클라이언트 접속


▲외부 인터넷을 잡은 클라이언트 영상


클라이언트는 서버보다 간단하다.

단지 서버의 ip와 port를 알고 있다면 Socket 클래스를 이용하여 객체를 생성하자마자 연결되기 때문이다.

 

1
2
3
Socket socket = new Socket(id address, iPort);
InputStream InputStream = socket.getInputStream();
OutputStream OutputStream = socket.getOutputStream();

cs

 


서버 때와 마찬가지로 Thread를 사용해야 입출력을 동시에 할 수 있으니 그것을 구현해야 한다.


Diagram을 참조하여 프로그램을 만든다.


서버소켓을 만들 때 필요한 건 ServerSocket 클래스 이다.

ServerSocket 클래스의 생성자 중 Port를 파라미터로 사용하는 생성자가 있는데 이를 사용하여 객체를 생성한다.


그리고 ServerSocket에 있는 accept 메소드를 이용하여 클라이언트가 접근할 때 까지 대기한다.

접속을 했을 경우 생기는 Socket을 반환하여 그것을 통해 입출력을 얻어 사용하면 된다.


이때 쓰레드로 구현하지 않을 경우 단순하게 서버와 클라이언트 간의 1:1 접속이 되지만 쓰레드로 구현할 경우 멀티 소켓 프로그램이 되는 것 이다. 하지만 Socket을 받았을 때 이것을 Thread없이 돌릴경우 입력 또는 출력만 할 수 있게되므로 Thread를 구현하여 입출력을 받을 수 있게 해야한다.


 

1
2
3
4
5
ServerSocket serverSocket = new ServerSocket(m_iPort);
 
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
cs


stream은 byte타입으로 read(),write(byte[] obj)를 이용하여 데이터를 송수신한다.

집에서 서버를 열 때 공유기를 사용하면 외부에서 바로 연결하지 못하고 공유기에서 포트를 열어줘야 한다.

1. 고정아이피 설정해주기

유동아이피 일경우 특정 아이피에 포트를 열어주더라도 나중에 IP가 변경되어 포트를 다시열어줘야 되는 경우가 생겨 장금해준다.

사용하는 공유기마다 다르지만 ipTime에서는 고급설정-네트워크 관리-내부 네트워크 설정 으로 들어간다.


2. 포트포워드 설정하기

고정한 IP주소를 적고 외부에서 접속할 때 사용하는 포트와 내부에서 접속할 때 사용할 포트를 기제후 추가한다.


첨부파일

TCPView 컴퓨터에서 사용하고 있는 TCP/UDP 포트를 보여주는 프로그램

https://technet.microsoft.com/ko-kr/library/bb897437.aspx


TCPView.zip


+ Recent posts