반응형

 개발을 안하는 사람들이라도 Url은 잘 알 것이다. 단순하게 '웹 주소'이기 때문에 인터넷을 사용하다보면 종종 볼 수

있다. 

 

 우선 이 두개의 용어가 정확히 어떤 의미를 가지고 있는지 알아보자.

 

 Uri(통합 자원 식별자, Uniform Resource Identifier)은 인터넷 자원을 나타내는 고유한 식별자로써, 쉽게 말해 인터넷에

있는 자료들의 아이디라고 생각하면 편할 것 같다. 아이디인 만큼 고유한 성격을 가진다. 

 안드로이드 앱개발 시점에서 본다면, Uri의 역할은 전화, 이미지, 지도, 텍스트 등의 리소스에 접근 할 수 있는 유일한

식별자라는 것이다.  

 

 Url(통합 자원 위치자, Uniform Resource Locator)은 위에서 말했다시피 '웹 주소'라고도 하며, 인터넷 네트워크 상에서 리소스가 어디에 있는지 알려주기 위한 것이다. Uri에 포함되어있다. 

 

Url은 Uri에 포함되어있지만 이 둘이 차이점은 Uri는 식별하고, Url은 위치를 가리킨다는 점이다. 

 

 

반응형
반응형

블로그 닉네임이자 내 개인 닉네임인 하빌리즘.

내 이름 + 알고리즘(개발 알고리즘과 큐브 알고리즘의 중의성)으로 21년 3월 16일날 닉네임을 만들게 되었다.

 

닉네임을 만들 당시에...알고리즘의 리즘을 -ism으로 순간 착각해버리는 바람에..ㅋㅋㅋㅋㅋㅋㅋㅋ

Habilism으로 만들게되었고...후에 -ithm라는 것을 인지했지만 스펠링이 Habilism이 더 멋있다고 생각해서 냅뒀다..ㅋㅋ

 

하지만 이제와서 바꾸려고한다!

아쉽게도 블로그 주소는 못 바꾸지만...어쩔 수 없지 뭐

 

다시 잘 부탁합니다 !

 

 

반응형

'잡담' 카테고리의 다른 글

개발 블로그 시작(21.04.10)  (0) 2021.04.10
반응형

< 하빌리즘 >('https://habilism.tistory.com/'이하 '하빌리즘 프로그래밍')은(는) 「개인정보 보호법」 제30조에 따라 정보주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립·공개합니다.

○ 이 개인정보처리방침은 2021년 11월 29부터 적용됩니다.

 

제1조(개인정보의 처리 목적)
- 하빌리즘은 처리할 개인정보가 없습니다. 



제2조(개인정보의 처리 및 보유 기간)
- 하빌리즘은 처리 및 보유할 개인정보가 없습니다. 



제3조(개인정보의 제공 및 공유)

- 하빌리즘은 제공 및 제 3자에게 공유할 개인정보가 없습니다. 

 

제4조(수집한 개인정보의 취급 위탁)

- 하빌리즘은 개인정보를 수집 및 이용하지 않습니다. 

 

제5조(개인정보의 파기)

- 하빌리즘은 파기할 개인정보가 없습니다. 

 

제7조(개인정보 자동 수집 장치의 설치•운영 및 거부에 관한 사항)
- 하빌리즘 은(는) 정보주체의 이용정보를 저장하고 수시로 불러오는 ‘쿠키(cookie)’를 사용하지 않습니다.

 

제8조 (개인정보 보호책임자)

 하빌리즘 은(는) 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호책임자를 지정하고 있습니다.

  • ▶ 개인정보 보호책임자
  • 성명 :김하빈
  • 직책 :대표
  • 직급 :대표
  • 메일 : sgsg617@naver.com

② 정보주체께서는 하빌리즘 의 서비스(또는 사업)을 이용하시면서 발생한 모든 개인정보 보호 관련 문의, 불만처리, 피해구제 등에 관한 사항을 개인정보 보호책임자 및 담당부서로 문의하실 수 있습니다. 하빌리즘 은(는) 정보주체의 문의에 대해 지체 없이 답변 및 처리해드릴 것입니다.

 

제9조(개인정보 열람청구)
정보주체는 「개인정보 보호법」 제35조에 따른 개인정보의 열람 청구를 아래의 부서에 할 수 있습니다.
< 하빌리즘 >은(는) 정보주체의 개인정보 열람청구가 신속하게 처리되도록 노력하겠습니다.

제10조(권익침해 구제방법)


정보주체는 개인정보침해로 인한 구제를 받기 위하여 개인정보분쟁조정위원회, 한국인터넷진흥원 개인정보침해신고센터 등에 분쟁해결이나 상담 등을 신청할 수 있습니다. 이 밖에 기타 개인정보침해의 신고, 상담에 대하여는 아래의 기관에 문의하시기 바랍니다.

1. 개인정보분쟁조정위원회 : (국번없이) 1833-6972 (www.kopico.go.kr)
2. 개인정보침해신고센터 : (국번없이) 118 (privacy.kisa.or.kr)
3. 대검찰청 : (국번없이) 1301 (www.spo.go.kr)
4. 경찰청 : (국번없이) 182 (ecrm.cyber.go.kr)

「개인정보보호법」제35조(개인정보의 열람), 제36조(개인정보의 정정·삭제), 제37조(개인정보의 처리정지 등)의 규정에 의한 요구에 대 하여 공공기관의 장이 행한 처분 또는 부작위로 인하여 권리 또는 이익의 침해를 받은 자는 행정심판법이 정하는 바에 따라 행정심판을 청구할 수 있습니다.

※ 행정심판에 대해 자세한 사항은 중앙행정심판위원회(www.simpan.go.kr) 홈페이지를 참고하시기 바랍니다.

제11조(개인정보 처리방침 변경)

 

① 이 개인정보처리방침은 2021년 11월 29부터 적용됩니다.

② 이전의 개인정보 처리방침은 아래에서 확인하실 수 있습니다.

예시 ) - 20XX. X. X ~ 20XX. X. X 적용 (클릭)

예시 ) - 20XX. X. X ~ 20XX. X. X 적용 (클릭)

예시 ) - 20XX. X. X ~ 20XX. X. X 적용 (클릭)

반응형
반응형

 '리사이클러뷰(RecyclerView)'는 아이템 뷰를 '인플레이션(Inflation, 팽창)'시켜서 리스트 형식으로 나타내며

앱을 제작할 때 많이 사용되는 뷰 중 하나이다. 

 아이템을 추가하고, 수정하고, 삭제하기 등의 처리를 하고 업데이트를 하는 것이 핵심적이기 때문에

확실히 알아두는 것이 중요하다. 

 

 아이템들은 ArrayList에 담아두고 관리하고, 필요한 메소드들을 호출한 후에 업데이트하는 방식으로

리사이클러뷰를 처리하게되는데, 이렇게 아이템들을 업데이트하는 5가지 방법에 대해서 알아보자. 

 

 우선 5가지 업데이트 방법에는 전체 갱신, 변경, 추가, 삭제, 이동 이 있다. 

 

 첫 번째로는 '전체 갱신'이다. 이 때 사용하는 메소드가 notifyDataSetChanged()인데, 사용하기 편하고

자주 사용한다. 이 메소드는 리스트의 크기와 아이템이 모두 변경되는 경우에 사용하면 되므로

어느 상황에서나 사용 가능하다는 장점이 있지만 웬만하면 각 상황에 해당되는 메소드들을 사용해주는 것이 좋다. 

 

 두 번째로는 '변경'이다. 일부만 바꾸고 싶은 경우 굳이 전체를 갱신할 필요가 없으므로 특정 위치의 아이템만 바꾸고

싶으면 이 메소드들을 사용하면 되는데 notifyItemChanged() 메소드와 notifyItemRangeChanged() 메소드가 있다. 

 

notifyItemChanged() 메소드는

notifyItemChanged(int position)와 notifyItemChanged(int position, Object payload)가 있는데

position은 변경된 아이템의 위치, payload는 어댑터의 onBindHolder()가 호출될 때 넘겨받는 객체이다. 

 

notifyItemRangeChanged() 메소드는

notifyItemRangeChanged(int positionStart, int itemCount)와 notifyItemRangeChanged(int position, int itemCount, 

Object payload)가 있는데 positionStart는 변경된 첫 번째 아이템의 위치, itemCount는 변경된 아이템의 개수, 

payload는 어댑터의 onBindHolder()가 호출될 때 넘겨받는 객체이다. 위 notifyItemChanged() 메소드와는 다르게

변경된 아이템이 복수의 아이템일 때 사용한다. 

 

 세 번째는 '추가'이다.

notifyItemInserted(int position) : 특정 위치에 새 아이템을 삽입할 때 사용한다. 

파라미터의 position이 0부터 시작한다는 것에 유의해야한다. 

notifyItemRangeInserted(int positionStart, int itemCount) : 복수의 아이템을 삽입할 때 사용한다. 

 

 네 번째는 '삭제'이다. 

notifyItemRemoved(int position) : 특정 위치의 아이템 1개를 삭제할 때 사용한다. 

notifyItemRangeRemoved(int positionStart, int itemCount) : 복수의 아이템을 삭제할 때 사용한다. 

 

 마지막으로는 '이동'이다. 

notifyItemMoved(int fromPosition, int toPosition) : 아이템의 순서가 변경되는 등 아이템을 이동할 때 사용한다. 

 

 이렇게 리사이클러뷰의 아이템들을 업데이트하는 방법에 대해 알아보았다. 

앱개발자라면 자주 사용하는 리사이클러뷰이기 때문에 확실히 알아두도록 하자.

 

피드백은 언제나 환영입니다. 

반응형
반응형

 라디오 버튼은 옵션이나 설문지 등 복수개의 선택지 중에서 하나를 선택할 때 사용하는 위젯이다. 

하지만 원하는 라디오 버튼에 체크를 해도 화면을 전환하거나 앱을 종료하게되면 체크했던 라디오 버튼이

해제되는 문제점이 있다. 설문지 같은 단순히 체크 후 제출하는 식의 라디오 버튼은 상태를 저장할 필요까진

없지만, 환경설정 같은 옵션 체크는 체크 후에 상태가 항상 유지되어야하기 때문에 체크 상태 저장이 필요하다.

 

 이렇게 상태를 저장하기위해 사용하는게  'SharedPreferences'이다. 

이 SharedPreferences는 앱 안에 파일을 하나 생성하고 그 안에 데이터를 저장해서 앱 재실행 시 데이터들을 복원할 수

있게 해주는데, 이번 시간에는 라디오 버튼 체크 상태를 이 파일 안에 저장 및 복원해서 상태를 유지하는 방법을

알아보도록 하겠다.  

 

 저번 시간에는 라디오 버튼을 라디오 그룹 안에 배치를 해서 처리를 했지만, 이번 시간에는 '컴파운드 버튼(CompoundButton)' 클래스로 된 라디오 버튼을 처리해보도록 할 것이다. 

 

 그런데 CompoundButton이란 무엇인가? 

Button 클래스의 하위 클래스 및 4가지 버튼들의 상위 클래스로, 그 하위 목록에는 '체크박스(Check Box)',

'토글 버튼(Toggle Button)', '라디오 버튼(Radio Button)', '스위치(Switch)'가 있고, 리스너로 OnCheckedChangeListener()를 추가로 사용할 수 있다.  

 

 

 이제 코드로 알아보자.

두 개의 라디오 버튼을 만들고, 각 버튼을 누른 상태에서 앱을 재실행시키게되면 최근에 선택했던 버튼이 저장되어

그 상태를 유지할 수 있도록하는 코드이다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
autoBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean auto_isChecked) {
                Toast.makeText(getApplicationContext(), "메모가 자동으로 저장됩니다. ", Toast.LENGTH_SHORT).show();
            }
        });
 
        manualBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean manual_isChecked) {
                Toast.makeText(getApplicationContext(), "메모가 수동으로 저장됩니다. (저장버튼 활성화) ", Toast.LENGTH_SHORT).show();
            }
        });
cs

 이렇게 각각의 버튼을 누를 때마다 각각의 처리를 기술하면된다. 

 

여기까지만 하면 체크 상태 저장은 되지 않는다. SharedPreferences를 이용해서 별도의 메소드를 만들어야한다. 

 

1
2
3
4
5
6
7
8
9
10
11
 private void RadioStateSave(String key, boolean value) {
        SharedPreferences sharedPreferences = getSharedPreferences("radio_State", MODE_PRIVATE); // "radio_state"라는 이름으로 파일생성, MODE_PRIVATE는 자기 앱에서만 사용하도록 설정하는 기본값
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putBoolean(key, value); // 키와 값을 boolean으로 저장
       editor.apply(); // 실제로 저장
    }
 
    private boolean UpdateState(String key) {
        SharedPreferences sharedPreferences = getSharedPreferences("radio_State", MODE_PRIVATE);
        return sharedPreferences.getBoolean(key, false);
    }
cs

 

위와 같이 저장 및 복원 메소드들을 만들었고, 이 메소드들을 onCreate()에서 다음과 같이 호출해주면 상태를 복원할 수가 있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
autoBtn.setChecked(UpdateState("auto"));
        manualBtn.setChecked(UpdateState("manual"));
 
        autoBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean auto_isChecked) {
                RadioStateSave("auto", auto_isChecked);
                Toast.makeText(getApplicationContext(), "메모가 자동으로 저장됩니다. ", Toast.LENGTH_SHORT).show();
                saveBtn.setVisible(true);
            }
        });
 
        manualBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean manual_isChecked) {
                RadioStateSave("manual", manual_isChecked);
                Toast.makeText(getApplicationContext(), "메모가 수동으로 저장됩니다. (저장버튼 활성화) ", Toast.LENGTH_SHORT).show();
                saveBtn.setVisible(false);
            }
        });
cs

피드백은 언제나 환영입니다. 

반응형
반응형

 앱을 이용할 때에 웹서버에서 정보를 가져와서 활용해야할 때가 많다. 이럴 때 사용하는 것이 Volley, Json, GSON 등이 있는데, 이번 시간에는 조회 버튼을 누르면 로또 회차별로 당첨 번호를 조회하는 기능을 공부해보겠다. 

 

 우선 Volley, Json, GSON을 간단하게 알아보고 시작하자.

 Volley는 웹 요청과 응답을 단순화하기 위해 만든 라이브러리로써, 먼저 요청 객체를 만들고, 이것을 요청 큐라는 곳에 넣어주기만 하면 요청 큐가 알아서 요청하고 응답을 받아주기까지하므로 간편하게 사용할 수 있다. 

 

 JSON은 자바스크립트 객체 포맷을 데이터를 주고 받을 때 사용할 수 있도록 문자열을 표현한 것이다. 

 Gson은 JSON 문자열을 자바 객체로 만들 수 있는데, Volley를 사용해서 웹서버로부터 JSON 응답을 받았다면

Gson을 이용해서 자바 객체로 바꾸고, 그 객체 안에 있는 데이터를 접근하여 사용할 수 있다. 

 

 이제 로또 당첨 번호를 가져와서 조회하는 앱의 UI는 다음과 같다.

 

EditText로된 회차번호 입력란에 본인이 원하는 회차를 입력하면 그에 맞는 당첨번호가 보라색(TextView)에 표시되는 것이다. 

 

 먼저, 기능적인 코드를 작성하기 전에 build.gradle(Module:app)에 필요한 라이브러리를 추가한다. 

1
2
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.android.volley:volley:1.1.1'
cs

그리고 웹서버에 요청하고 응답받는 교류를 해야하므로 매니페스트에서 인터넷 권한을 준다. 

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

다음은 구체적인 기능 코드이다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class MainActivity extends AppCompatActivity {
 
    TextView tv;
    Button btn;
    EditText edt;
 
    RequestQueue requestQueue;
    JsonObject jsonObject;
 
    String num; // 로또 회차번호
    String[] nums = {"drwtNo1""drwtNo2""drwtNo3""drwtNo4""drwtNo5""drwtNo6""bnusNo"}; // 당첨번호 배열
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        tv = (TextView)findViewById(R.id.tv);
        edt = (EditText)findViewById(R.id.edt);
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                requestNums();
            }
        });
 
        // RequestQueue 객체 생성 -> 여러번 생성되는 것을 방지함
        if(requestQueue == null) {
            requestQueue = Volley.newRequestQueue(getApplicationContext());
        }
    }
 
    public void requestNums() {
        num = edt.getText().toString();
        if(num.equals("")) { // 회차 번호를 입력하지 않았을 경우
            Toast.makeText(getApplicationContext(), "회차 번호를 입력하세요. ", Toast.LENGTH_SHORT).show();
            return;
        }
 
        String url = "https://www.dhlottery.co.kr/common.do?method=getLottoNumber&drwNo=" + num; // api 링크를 가져와서 url 변수에 할당
 
        // 문자열을 주고 받기위해 사용하는 요청 객체
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { // 웹서버 요청시 방식구분, 어떤 url요청?, 응답을 문자열로 받아서 여기에 넣기
            @Override
            public void onResponse(String response) {
                // JsonObject는 객체를 Json 객체로 바꿔주거나 Json 객체를 새로 만드는 역할
                jsonObject = (JsonObject) JsonParser.parseString(response);
 
                String data = num + "회차 당첨번호 : ";
 
                for (int i = 0; i < nums.length - 1; i++) { // 당첨번호 배열 크기만큼 반복
                    data += jsonObject.get(nums[i]) + ", "// 당첨번호 6개와
                }
                data += " 보너스 : " + jsonObject.get(nums[nums.length - 1]); // 보너스 번호를
                tv.setText(data); // TextView에 출력
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) { // 응답이 에러났을 경우
            }
        }) {
            protected Map<String,String> getParams() throws AuthFailureError {
                Map<String,String> params = new HashMap<>();
                return params;
            }
        };
        request.setShouldCache(false); // 이전 응답 결과를 사용하지 않겠다면 cache를 사용하지 않도록 false
        requestQueue.add(request); // 요청 큐에 요청 객체 넣기 -> 요청 큐가 알아서 요청과 응답 과정 진행
    }
}
cs

최종 출력 화면, 당첨번호가 없는 회차를 입력하거나 숫자가 아닌 문자열을 입력하면 null값이 뜬다.

 

피드백은 언제나 환영입니다. 

반응형
반응형

 다른 액티비티의 메소드를 참조할 때에 다음과 같이 간단한 방법으로 코드를 작성할 수 있다. 

 

먼저, 호출하고 싶은 메소드가 있는 액티비티에 public static Context 변수를 생성하고, 

onCreate()에서 this로 지정한다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MainActivity extends AppCompatActivity {
 
    public static Context context;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        context = this;
 
cs

 

그리고 호출할 때에는 다음과 같이 작성해주면 된다. 

 

1
 ((MainActivity)MainActivity.context).saveMemo();
cs

 

피드백은 언제나 환영입니다. 

반응형
반응형

 안드로이드에서 환경설정이나 메뉴같은 것들을 사용할 때에 원하는 옵션을 선택하기 위하여 동그라미에 체크했던 

경험이 다들 한번씩은 무조건 있을 것이라고 생각된다. 이것이 라디오 단추와 비슷하다고 생각해서 지어진 이름이

'라디오 버튼(Radio Button)' 이다. 

 

 라디오 버튼은 복수의 선택지 중에서 하나만 선택할 수 있도록 되어 있고, 이러한 버튼들은 '라디오 그룹(Radio Group)'

안에 배치해야만(말 그대로 그룹화해야만) 한 세트로 인식하고 한번에 하나의 버튼만 선택할 수 있도록 동작한다. 

 

다음 xml 코드를 통해 알아보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  <RadioGroup
                android:id="@+id/radioGroup"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:checkedButton="@id/autoBtn">
 
                <RadioButton
                    android:id="@+id/autoBtn"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="메모 자동저장" />
 
                <RadioButton
                    android:id="@+id/manualBtn"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="메모 수동저장"/>
 
</RadioGroup>
cs

 

위와 같이 라디오 그룹 안에 라디오 버튼들을 넣어준다. 

 

 라디오 그룹을 보면 checkButton 이라는 속성이 보일 것이다. 이 속성은 라디오 그룹 안에 있는 라디오 버튼들 중에서 처음에 눌러져 있는 디폴트 값이다. 위와 같은 경우에는 두 개의 라디오 버튼 중에서 autoBtn, 즉 '메모 자동 저장' 

버튼이 초기 상태로 눌러져 있다는 것이다. 

 

그리고 라디오 버튼을 동작시키기 위한 코드를 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 radioGroup = (RadioGroup)findViewById(R.id.radioGroup);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if(checkedId == R.id.autoBtn) {
                    Toast.makeText(getApplicationContext(), "메모가 자동으로 저장됩니다. ", Toast.LENGTH_SHORT).show();
                    saveBtn.setVisible(false);
                }
                else if(checkedId == R.id.manualBtn) {
                    Toast.makeText(getApplicationContext(), "메모가 수동으로 저장됩니다. (저장버튼 활성화) ", Toast.LENGTH_SHORT).show();
                    saveBtn.setVisible(true);
                }
            }
        });
cs

 라디오 그룹 내의 라디오 버튼들을 누르게 되면 각 버튼 마다의 id값을 구분해서 원하는 동작을 구현할 수 있다. 

 

피드백은 언제나 환영입니다. 

반응형

+ Recent posts