전체 글 (28)

평상시에 잘 사용해오던 윈도우 10 기본 기능인 프로그램 검색기능이 먹통이 되는 문제가 발생했다.



검색어를 입력해도 아무런 결과가 출력되지 않는다.



이럴때의 해결방법에 대해 알아보도록 하자.



해결 방법 1.


1) 키보드 좌측 하단의 Ctrl 키와 Alt 키 사이의 "윈도우키 + x" 를 클릭한 후 Windows PowerShell(관리자)를 클릭한다.


2) 실행된 파워셀 창에 아래의 코드를 복사, 붙여넣기 한 후 엔터를 친다. 그러면 1~2분 정도 소요되며 자동으로 프로그램을 재설치한다.

간혹 빨간색 글씨로 여러가지 문제점이 출력될 수 있는데, 그것들은 무시해도 상관없다.


Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register “$($_.InstallLocation)\AppXManifest.xml”}


3. 작업이 완료되면 컴퓨터를 재부팅하고 검색기능을 확인한다.






해결 방법 2.


1) 키보드 좌측 하단의 Ctrl 키와 Alt 키 사이의 "윈도우키 + x" 를 클릭한 후 Windows PowerShell(관리자)를 클릭한다.


2) 실행된 파워셀 창에 아래의 코드를 복사, 붙여넣기 한 후 엔터를 친다. 그러면 1~2분 정도 소요되며 자동으로 프로그램을 재설치한다.

간혹 빨간색 글씨로 여러가지 문제점이 출력될 수 있는데, 그것들은 무시해도 상관없다.


Dism /online /cleanup-image /restorehealth


3) 작업이 완료되면 아래의 코드를 복사, 붙여넣기 한 후 엔터를 친다.


sfc /scannow


4) 작업이 완료되면 컴퓨터를 재부팅하고 검색기능을 확인한다.





해결 방법 3.


1) 키보드 좌측 하단의 Ctrl 키와 Alt 키 사이의 "윈도우키 + r" 를 클릭한 후 열리는 실행창에 services.msc를 입력하고 엔터를 친다.


2) 열린 서비스 창에서 Windows Search를 찾아 상태가 "실행중", 시작 유형이 "자동(지연된 시작) 인지 확인한다.


3) 상태가 "실행중", 시작 유형이 "자동(지연된 시작)"이 아닐경우, Windows Search를 더블클릭하여 서비스 상태 시작을 클릭하고, 시작 유형을 "자동(지연된 시작)"으로 변경한 후 적용 -> 확인 버튼을 클릭한다. 


4) 마우스 오른쪽 클릭 후 다시 시작을 클릭한다.


5) 작업이 완료되면 컴퓨터를 재부팅하고 검색기능을 확인한다.






해결 방법 4.


1) 키보드 좌측 하단의 Ctrl 키와 Alt 키 사이의 "윈도우키 + r" 를 클릭한 후 열리는 실행창에 services.msc를 입력하고 엔터를 친다.


2) 열린 서비스 창에서 Application Identity를 찾아 상태가 "실행중", 시작 유형이 "자동(지연된 시작) 인지 확인한다.


3) 상태가 "실행중", 시작 유형이 "자동(지연된 시작)"이 아닐경우,  Application Identity를 더블클릭하여 서비스 상태 시작을 클릭하고, 시작 유형을 "자동(지연된 시작)"으로 변경한 후 적용 -> 확인 버튼을 클릭한다. 


4) 마우스 오른쪽 클릭 후 다시 시작을 클릭한다.


5) 작업이 완료되면 컴퓨터를 재부팅하고 검색기능을 확인한다.





해결 방법 5.


1) 윈도우가 업데이트 되면서 생기는 버그일 수도 있기 때문에 윈도우의 최신 업데이트를 확인한다.


2) 키보드 좌측 하단의 Ctrl 키와 Alt 키 사이의 "윈도우키" 를 클릭한 후 컴퓨터 종료버튼 위의 설정(톱니바퀴) 버튼을 클릭한다.


3) 열린 설정 창에서 가장 아래의 "업데이트 및 보안" 을 클릭한다.


4) "업데이트 확인" 버튼을 클릭한 후 , "현재 최신 상태입니다." 가 아니라면 업데이트를 지금 다운로드 및 설치한다.


5) 작업이 완료되면 컴퓨터를 재부팅하고 검색기능을 확인한다.





마이크로 소프트에서 공식적으로 추천하는 방법은 1, 2, 5번 방법입니다.


업데이트 후 버그로 인한 문제가 자주 발생하기 때문에 첫번째로는 윈도우 업데이트를 확인하는 것이 가장 빠르고


업데이트를 했음에도 해결되지 않는 경우에는 1, 2번 방법을 순서대로 이용하신다면 대부분 문제가 해결될것이라고 생각됩니다.


혹시 5가지 방법을 모두 사용했는데도 해결되지 않으실 경우 답글 남겨주시면 확인해보도록 하겠습니다.



오사카 알약 개인정보취급방침

1. 개인정보의 처리 목적. 


본 개발자가 작성한 오사카 알약 - 어디까지알아? 은(는) 다음의 목적을 위하여 개인정보를 처리하고 있으며, 다음의 목적 이외의 용도로는 이용하지 않습니다.

1) 해당 앱에서 구글 Admob 광고가 필요로 하는 권한 위임을 위해 사용

2. 개인정보처리 위탁 여부
본 개발자의 앱은 타 업체에 개인정보처리를 위탁하지 않습니다.

3. 정보주체의 권리,의무 및 그 행사방법
이용자는 개인정보주체로서 언제든지 개인정보 보호 관련 권리를 행사할 수 있습니다.
다만, 본 앱은 앱 사용자의 사용정보를 수집 및 보유하지 않습니다.

4. 처리하는 개인정보의 항목 작성
다음의 개인정보 항목을 처리하고 있습니다.


android.permission.INTERNET: Admob 광고를 위해 사용합니다.
android.permission.ACCESS_NETWORK_STATE: : Admob 광고를 위해, 모바일 네트워크 사용 유무 확인을 위해 사용합니다.

5. 개인정보의 파기
앱 사용자의 사용정보를 수집 및 보유하지 않습니다.

6. 개인정보의 안전성 확보 조치
앱 사용자의 사용정보를 수집 및 보유하지 않습니다.


저번 포스팅에서 만들었던 Google Play Console 개발자 계정 등록 이외에도 본인이 만든 애플리케이션에 인앱결제,


즉 게임 아이템을 결제하거나 광고제거 등을 만들기 위해서는 추가적으로 "판매자 계정"을 설정해야 한다.


단순 광고수익 뿐만 아니라 좀 더 많은 수익을 창출할 수 있는 인앱 결제 방법에 대해서 알아보자.


1. Google Play Console에 접속, 로그인한다.

https://developer.android.com/distribute/console?hl=ko



2. 왼쪽의 "주문 관리"를 클릭한 후, "판매자 계정 설정"을 클릭한다.


3. 판매자 가입 화면에서 고객정보, 공개 판매자 프로필을 입력하고 "제출" 버튼을 클릭한다.

(신용카드 명세서 이름이란, 구매자의 결제내역에 표시되는 내용이며 한글이 입력되지 않는듯 합니다.)


4. 입력 내용에 오류가 없다면 이와같은 화면이 나옵니다.


판매자 계정 승인이 완료되면, 이제부터 인앱결제를 통한 인앱 상품을 판매할 수 있게 되었습니다.




개발자 분들중에 티스토리에 본인의 코드나, 앞으로 꾸준히 사용할것 같은 코드들을 정리해두시는 분들이 많습니다.


이번에 새로나온 티스토리 글 작성 에디터에는 코드입력기가 따로 있는것같은데, 저는 이미지 업로드 버그때문에 현재 구버전 에디터를 사용하고 있습니다.


구버전 에디터에는 코드입력기가 따로 없어서 그런 분들을 위한 설명이라고 생각하시면 될것같습니다.



코드 입력에 가장 쉬운방법으로는 본인이 사용하고 계시는 작업툴 (여기서는 안드로이드 스튜디오) 에서 코드를 복사, 붙여넣기 하시면 자동으로 

작업툴 테마에 맞춰 코드가 복사됩니다.


TextView tv_preparation = convertView.findViewById(R.id.item_text);
CheckBox checkBox = convertView.findViewById(R.id.checkbox);


하지만 코드 줄번호도 없고, 한눈에 보기에 편하다는 느낌을 주지는 않습니다.


그래서 소개해드리는 사이트입니다.


https://colorscripter.com/ 에 접속하셔서 본인의 코드를 복사 - 붙여넣기 하시면 됩니다.


입력한 대부분의 언어를 자동으로 인식하여 보기 편하게 하이라이트해주고, 자동정렬해줍니다. 또한 코드 줄번호도 자동으로 생성해주기때문에 


특정 코드를 설명하는데 편리합니다, (5~10번줄은 00 함수에 관련된 코드입니다 같은 형식으로 이해하기 쉬운 설명이 가능합니다.)



또한 세부설정을 클릭하면 코드에 사용할 글꼴, 코드 줄간격, 줄번호 시작숫자, 가로세로 크기제한 등 여러가지 설정이 가능합니다.



본인의 코드를 복사 - 붙여넣기 하신 후에 화면 우측 하단의 "클립보드에 복사" 버튼을 클릭하신 후 작성하시고 계시는 티스토리 게시글에 붙여넣기 하시면 됩니다.



public class Preparation_Item {

boolean checked;
String ItemString;

Preparation_Item(boolean b, String t) {
checked = b;
ItemString = t;
}

public boolean isChecked() {
return checked;
}
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Preparation_Item {
 
    boolean checked;
    String ItemString;
 
    Preparation_Item(boolean b, String t){
        checked = b;
        ItemString = t;
    }
 
    public boolean isChecked(){
        return checked;
    }
}
 
cs



안드로이드 스튜디오에서 복사 - 붙여넣기 한것과 Scripter 사이트를 이용한 코드 비교입니다. 확실히 아래쪽이 훨씬 더 보기 편하고 코드 줄번호덕분에 설명하는데도 좋겠네요





안드로이드 개발은 쉬우면서도 어렵다.


이게 무슨 개소리냐면 머리로 구상한대로만 진행된다면 정말 그 어떤 코딩보다도 쉬운데


구상한대로 진행하다보면 꼭 생각지도 못한 문제가 발생한다.


이번에 진행할 Listview Checkbox 스크롤 문제도 그렇다.


나는 따로 Checkbox 값을 받아와야 하는 상황이 아니고, 체크박스에 체크만 하면 되기때문에 5분정도면 간단하게 구현할수 있을거라 생각했는데


Checkbox에 체크를 하고, 스크롤을 내렸다 올리면 다른 Checkbox에 체크되어있고, 원래 체크했던 Checkbox에는 체크가 지워지는 기이한 현상이 발생했다.



인터넷을 검색해보니, 자원을 아끼기 위해서 리스트뷰의 재사용 문제때문이란다.


리스트뷰에 총 30개의 row_item 이 있다고 하고, 한 화면에 10개가 출력된다고 할때, 리스트뷰는 한번에 30개를 로딩시켜놓는것이 아니라


대략 12개정도만 로딩시켜놓고, 화면을 스크롤하면 이전것들을 없앤 후에 12개째부터 24개까지 로딩시키는 방식을 사용한다고 한다.



이 글을 검색해서 들어오는 대부분의 사람들은 원인보다는 해결방안을 원할것이기 때문에 바로 해결방법에 대해 설명하도록 하겠습니다.




preparation_listview_item.xml => 리스트뷰에 들어갈 아이템

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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/item_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="준비물"
            android:textSize="30dp"
            android:layout_weight="2" />
        <CheckBox
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="8"
            android:gravity="center|right"
            android:id="@+id/checkbox"/>
    </LinearLayout>
</LinearLayout>
 
cs


fragment_preparation.xml => 리스트뷰가 있는 메인화면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="준비물을 확인해보세요!" />
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ListView>
</LinearLayout>
cs

preparation_item.java => 리스트뷰 아이템과 매칭시켜줄 데이터 객체

(저는 사진과 같이 체크박스 1개와 텍스트 1개로 이루어져 있어 간단하게 만들었고, 여러분은 본인 상태에 따라 이미지나 여러가지 변수를 추가하세요.)


1
2
3
4
5
6
7
8
9
10
11
public class Preparation_Item {
    boolean checked;
    String ItemString;
    Preparation_Item(boolean b, String t){
        checked = b;
        ItemString = t;
    }
    public boolean isChecked(){
        return checked;
    }
}
cs

** 스크롤 후 체크 이상현상을 해결하기 위해서는 데이터 객체에 반드시 boolean checked 값을 저장하고 있어야 합니다 **


arrays.xml => res/values/arrays.xml 생성 후 리스트뷰 아이템에 들어갈 값 저장.


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
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="restext">
        <item>"여권"</item>
        <item>"여권사본"</item>
        <item>"여권사진"</item>
        <item>"체크카드"</item>
        <item>"환전한 돈"</item>
        <item>"한국 돈"</item>
        <item>"지갑"</item>
        <item>"동전지갑"</item>
        <item>"여행용 책"</item>
        <item>"옷"</item>
        <item>"모자"</item>
        <item>"보조배터리"</item>
        <item>"휴대폰 충전기"</item>
        <item>"이어폰"</item>
        <item>"돼지코"</item>
        <item>"선크림"</item>
        <item>"선글라스"</item>
        <item>"라면"</item>
        <item>"볼펜"</item>
        <item>"수첩"</item>
        <item>"비상약"</item>
        <item>"바우처"</item>
        <item>"패스"</item>
        <item>"빨래 지퍼백"</item>
        <item>"슬리퍼"</item>
        <item>"세면도구"</item>
        <item>"여행용 티슈"</item>
        <item>"멀티어댑터"</item>
        <item>"셀카봉"</item>
        <item>"예비안경"</item>
        <item>"안경닦이"</item>
        <item>"렌즈"</item>
        <item>"물병"</item>
        <item>"휴대용 가방"</item>
    </array>
</resources>
 
cs


PreparationFragment.java

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
public class PreparationFragment extends Fragment {
    ListView listView;
    ArrayList<Preparation_Item> items;
    public PreparationFragment() {
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_preparation, container, false);
        initItems();
        listView = v.findViewById(R.id.listView);
        Preparation_Adapter mAdapter = new Preparation_Adapter(items);
        listView.setAdapter(mAdapter);
        return v;
    }
// arrays.xml 값을 불러와 Preparation_Item 객체에 저장하는 함수. 처음에는 체크박스에 체크가 되어있지 않기때문에 boolean은 false를 저장한다.
    private void initItems(){
        items = new ArrayList<Preparation_Item>();
        TypedArray arrayText = getResources().obtainTypedArray(R.array.restext);
        for(int i=0; i<arrayText.length(); i++){
            String s = arrayText.getString(i);
            boolean b = false;
            Preparation_Item item = new Preparation_Item(b, s);
            items.add(item);
        }
        arrayText.recycle();
    }
}
 
cs


Preparation_Adapter.java

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
public class Preparation_Adapter extends BaseAdapter {
    private ArrayList<Preparation_Item> list;
// 어댑터 생성시 PreparationFragment.java 에서 만들었던 데이터 객체 리스트를 초기화
    Preparation_Adapter(ArrayList<Preparation_Item> i){
        list = i;
    }
    @Override
    public int getCount() {
        return list.size();
    }
    @Override
    public Object getItem(int position) {
        return list.get(position);
    }
    @Override
    public long getItemId(int position) {
        return 0;
    }
    public boolean isChecked(int position) {
        return list.get(position).checked;
    }
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        Context context = parent.getContext();
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.preparation_listview_item, parent, false);
        }
        TextView tv_preparation = convertView.findViewById(R.id.item_text);
        CheckBox checkBox = convertView.findViewById(R.id.checkbox);
        checkBox.setChecked(list.get(position).checked);
        tv_preparation.setText(list.get(position).ItemString);
        checkBox.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view){
                boolean newState = !list.get(position).isChecked();
                list.get(position).checked = newState;
            }
        });
        checkBox.setChecked(isChecked(position));
        return convertView;
    }
}
 
cs


빨간색으로 표현한 부분이 이번 코드의 가장 핵심포인트입니다.


리스트뷰에서 체크박스를 클릭하면, 체크박스의 setOnClickListener를 호출하여 클릭한 position의 preparation_item.java 객체 boolean 함수에

!list.get(position).isChecked(); check 였다면 => uncheck, uncheck 였다면 => check 로 바꿔서 저장시키고,


checkBox.setChecked(isChecked(position)); 그 값을 checkbox에 setChecked 하여 스크롤 후에도 체크된 것들이 그대로 남아있게 됩니다.


이 문제를 해결하기 위해서 구글을 어지간히 검색해봤는데, 대부분 재사용 현상때문이다, 해결하기 위해서는 boolean값을 따로 저장하고 있어야 한다.

정도의 답변밖에 찾질 못했습니다. 물론 맞는 정답이기는 한데, 저같은 초보들은 이런식으로 코드가 있어야 확실히 이해하기 편하거든요.


앞으로도 코딩하면서 제가 여기저기 검색해서 구현 완료된 내용들에 대해서는 이런식으로 정리해서 올려드리도록 하겠습니다.


이해안가시는 부분이 있으시면 질문남겨주세요!