728x90

버튼의 경우 기본 속석으로 enable 속성이 있다.

다른 View 들도 마찬가지인데 button의 경우 enable(false)로 하게되면 error가 자꾸 나면서 App이 종료된다.


자꾸 종료되고 재시작되고...

결국 찾은 결론은 button의 경우는 click이 기본 기능이므로 clickable로 대체하는 것이다.

//btnStop.setEnabled(false);
btnStop.setClickable(false);

이렇게 하면 click 했을 때, true/false로 제어는 가능하지만 보이기로는 구분이 되지 않는다.

그래서 true일 때 보여주는 이미지, false일 때 보여주는 이미지를 같이 설정하도록 하면 된다.


728x90

ADMob 설정

2019. 3. 6. 00:41
728x90

admob 설정은 크게 두 개의 id 를 어디에 넣느냐에 달려있다.

string.xml 에 admob_app_id 와 banner_add_unit_id 값을 추가하면되는데



1. admob_app_id

admob 사이트에서

해당 앱의 앱설정에 나오는 앱 ID


androidManifest.xml 에 정의하는 값.

<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="@string/admob_app_id"/>


2. banner_add_unit_id

해당앱의 광고단위에 나오는 해당 단위에 나오는 값 ca-app-pub-xxx 값


activity 내 view로 정의할 때 사용

test용 banner_id 는 ca-app-pub-3940256099942544/6300978111

<com.google.android.gms.ads.AdView xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
ads:adSize="SMART_BANNER"
ads:adUnitId="@string/banner_ad_unit_id"><!-- @string/admob_app_id, banner test id : ca-app-pub-3940256099942544/6300978111 -->

</com.google.android.gms.ads.AdView>

3. activity내에서 사용시

MobileAds.initialize(this, getString(R.string.admob_app_id));
mAdView = findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);


728x90
728x90

다운로드 링크

https://play.google.com/store/apps/details?id=com.nobang.callforone


콜포원의 기능은 단순하다.

빅스비 버튼을 누르면 지정된 번호로 전화걸기.


이를 위해서 어플 설치 후 빅스비 설정을 해야 한다.

1. 설정 > 유용한 기능 > 빅스비 버튼을 터치


2. 빅스비는 무조건 사용해야 된다.

 - 시작하기 버튼 터치



3. 한번 눌렀을 때 실행 또는 두번 눌렀을 때 실행을 선택하면

나머지 경우에 콜포원을 지정하여 사용할 수 있다.


예로 다음과 같이 설정한다.

한번 눌렀을 때 : 콜포원 실행

두번 눌렀을 때 : 빅스비 실행


- 두번 눌러서 빅스비 열기 선택

- 한번 누르기 사용을 활성화



3. 한 번 누르기 사용 활성화

 - 사용안함 -> 사용함으로 바꾸면 앱열기도 활성화 됨.


4. 앱 열기 선택 후 톱니바퀴를 터치하면 실행할 앱목록이 나옴.


콜포원 ( call for one ) 을 선택



5. 설정에 맞게 빅스비 버튼을 누르면 (한번 또는 두번)

콜포원 설정화면이 나온다.

- 전화번호를 입력한다.

- 자동 전화걸기를 활성화 해야 5초 후 자동으로 전화가 걸린다.


6. 설정이 끝났으면 종료 후 다시 빅스비 버튼을 누르면

카운트 다운 5,4,3,2,1 이후 지정한 번호로 전화를 건다.

아래 3가지 경우에 전화걸기가 되지 않는다.


- 전화번호가 입력되지 않으면 동작하지 않음.

- 자동 전화걸기 활성화 되어있지 않으면 동작하지 않음.

- 통화중인 경우 동작하지 않음.




728x90
728x90

기존 app에 Admob광고를 붙이는 도중 광고가 나오지 않음.

소스에 문제는 없고 Test UnitID로도 배너광고가 나오는 것은 확인했는데


log를 보니

 The Google Mobile Ads SDK will not integrate with Firebase. Admob/Firebase integration requires the latest Firebase SDK jar, but Firebase SDK is either missing or out of date


위와 같은 메세지가 나왔다.

Tool > SDK Manager >  SDK Tool tab에서 google play service 가 체크되어있는지 확인

체크가 안되어있으면 설치가 안된 것이므로 체크하여 설치

728x90
728x90
사람 없기로 유명한 태백의 오투리조트

맨 왼쪽은 눈썰매장 이용객들
눈썰매장 에스컬레이터 있음

12시가 조금 안된 시각인데

진짜 보트타고 싶으면 오투 강추..
내년에는 꼭 탈테니까 망하지만 마.
728x90
728x90

여전히 사람이 없구마이~

나중에 꽤 들어오기는 했지만
혼자 영화보기
여유가 있으면 그렇게 재미있네
마음의 여유가 없을 때는 나오는 것도 싫었는데

보면서 혼자 어찌나 킥킥댔는지
잘 웃고 감
극한직업.
마치 만화를 보는듯한 재미였음
728x90
728x90
보증기간 만료 전 겨우 예약이 되어 방문
건물도 크고 멋지네

1층 한쪽(들어가서 왼쪽)은 전시장
정면에는 엘리베이터가 보이고 오른쪽으로 돌면 접수처가 있다
접수처 뒤로 엔지니어와 수리하는곳

접수대에 가서 예약정보 확인하고 2층가서 대기하라고 한다

2층이 대기실인데 도서관같이 책도 있고

개인용 공간도 있고

안마의자도 몇 개 있고

A/S받는거 볼 수 있는 자리도 있고

좋네~
컴퓨터 가져왔으면 딱 일하기 좋은 환경인데

커피와 쿠키를 주니까 일단 먹으면서 기다려보자
난 우유 ㅋ


조금있다가 차구경 가야지 ㅋ

미니 매장은 3층에 있다... 몰랐다 ㅜ.ㅜ

여기에서 현대아울렛가는 무료 셔틀버스가 있네
밥먹으러 가야하나?


728x90
728x90

이제 결과를 받아왔으니

적절하게 꾸며야지


27개의 Todo가 있다.


<!--TODO (1) Add a string stating that an error has occurred-->

strings.xml 부터 error 발생 시 보여줄 message 추가

<resources>
    <string name="app_name">GithubSearch</string>

    <string name="search">Search</string>

    <!--TODO (1) Add a string stating that an error has occurred-->
    <string name="error_message">
        Failed to get results. Please try again.
    </string>
</resources>


<!--TODO (2) Wrap the ScrollView in a FrameLayout-->
<!--TODO (3) Make the width and height of the FrameLayout match_parent-->
activity_main.xml 에 scrollview를 FrameLayout으로 감싸준다.

    <!--TODO (2) Wrap the ScrollView in a FrameLayout-->
    <!--TODO (3) Make the width and height of the FrameLayout match_parent-->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp">
            <TextView
                android:id="@+id/tv_github_search_results_json"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Make a search!"
                android:textSize="18sp" />
        </ScrollView>
    </FrameLayout> 


<!--TODO (4) Add a TextView to display an error message-->
<!--TODO (5) Set the text size to 22sp-->
<!--TODO (6) Give the TextView an id of @+id/tv_error_message_display-->
<!--TODO (7) Set the layout_height and layout_width to wrap_content-->
<!--TODO (8) Add 16dp of padding to the error display -->
<!--TODO (9) Use your strings.xml error message to set the text for the error message-->
<!--TODO (10) Set the visibility of the view to invisible-->
<!--TODO (11) Make this TextView a child of the FrameLayout that you added above-->

error message를 화면에 보여줄 수 있도록 Textview를 추가한다.

        <TextView
            android:id="@+id/tv_error_message_display"
            android:textSize="22sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:text="@string/error_message"
            android:visibility="invisible" /> 


<!--TODO (18) Add a ProgressBar to indicate loading to your users-->
<!--TODO (19) Give the ProgressBar an id of @+id/pb_loading_indicator-->
<!--TODO (20) Set the layout_height and layout_width to 42dp-->
<!--TODO (21) Set the layout_gravity to center-->
<!--TODO (22) Set the visibility of the ProgressBar to invisible-->
<!--TODO (23) Make this ProgressBar a child of the FrameLayout the you added above-->

처리되는 동안 표시 될 Progressbar를 추가한다.

        <ProgressBar
            android:id="@+id/pb_loading_indicator"
            android:layout_height="42dp"
            android:layout_width="42dp"
            android:layout_gravity="center"
            android:visibility="invisible" /> 


MainActivity를 수정한다.

순서상으로는 12(TextView 추가) 후 24(Progressbar 추가) 이나 xml을 먼저 정의 해 놓은 다음 처리했다.

// TODO (12) Create a variable to store a reference to the error message TextView
// TODO (24) Create a ProgressBar variable to store a reference to the ProgressBar

import android.widget.ProgressBar;
...
    // TODO (12) Create a variable to store a reference to the error message TextView
    private TextView mErrorMessageDisplay;
    // TODO (24) Create a ProgressBar variable to store a reference to the ProgressBar
    private ProgressBar mLoadingIndicator; 


// TODO (13) Get a reference to the error TextView using findViewById
// TODO (25) Get a reference to the ProgressBar using findViewById

onCreate method에 xml값과 변수를 매핑시킨다.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mSearchBoxEditText = (EditText) findViewById(R.id.et_search_box);
        mUrlDisplayTextView = (TextView) findViewById(R.id.tv_url_display);
        mSearchResultsTextView = (TextView) findViewById(R.id.tv_github_search_results_json);

        // TODO (13) Get a reference to the error TextView using findViewById
        mErrorMessageDisplay = (TextView) findViewById(R.id.tv_error_message_display);
        // TODO (25) Get a reference to the ProgressBar using findViewById
        mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);
    } 


// TODO (14) Create a method called showJsonDataView to show the data and hide the error
// TODO (15) Create a method called showErrorMessage to show the error and hide the data

jsonData를 보여줄 method 추가, errorMessage를 보여줄 method 추가

    // TODO (14) Create a method called showJsonDataView to show the data and hide the error
    private void showJsonDataView() {
        // First, make sure the error is invisible
        mErrorMessageDisplay.setVisibility(View.INVISIBLE);
        // Then, make sure the JSON data is visible
        mSearchResultsTextView.setVisibility(View.VISIBLE);
    }


    // TODO (15) Create a method called showErrorMessage to show the error and hide the data
    private void showErrorMessage() {
        // First, hide the currently visible data
        mSearchResultsTextView.setVisibility(View.INVISIBLE);
        // Then, show the error
        mErrorMessageDisplay.setVisibility(View.VISIBLE);
    } 


// TODO (16) Call showErrorMessage if the result is null in onPostExecute       
// TODO (17) Call showJsonDataView if we have valid, non-null results

inner class인 GithubQueryTask 의 onPostExecute에 결과를 보여주도록 추가

        @Override
        protected void onPostExecute(String githubSearchResults) {
            if (githubSearchResults != null && !githubSearchResults.equals("")) {
                // TODO (17) Call showJsonDataView if we have valid, non-null results
                showJsonDataView();
                mSearchResultsTextView.setText(githubSearchResults);
            } else {
                // TODO (16) Call showErrorMessage if the result is null in onPostExecute
                showErrorMessage();
            }
        } 


// TODO (26) Override onPreExecute to set the loading indicator to visible

inner class인 GithubQueryTask 의 onPreExecute 재정의(onPostExecute아님)

        // TODO (26) Override onPreExecute to set the loading indicator to visible
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mLoadingIndicator.setVisibility(View.VISIBLE);
        } 


// TODO (27) As soon as the loading is complete, hide the loading indicator

loading이 끝나자마다 indicator를 숨기도록 처리

onPostExecute 의 최종 결과임

    @Override
    protected void onPostExecute(String githubSearchResults) {
        // TODO (27) As soon as the loading is complete, hide the loading indicator
        mLoadingIndicator.setVisibility(View.INVISIBLE);
       
        if (githubSearchResults != null && !githubSearchResults.equals("")) {
            // TODO (17) Call showJsonDataView if we have valid, non-null results
            showJsonDataView();
            mSearchResultsTextView.setText(githubSearchResults);
        } else {
            // TODO (16) Call showErrorMessage if the result is null in onPostExecute
            showErrorMessage();
        }
    } 



728x90
728x90

이번에는 동기화를 진행하여 네트워크를 통한 조회결과를 가져오는 부분이다.


// TODO (1) Create a class called GithubQueryTask that extends AsyncTask<URL, Void, String>
// TODO (2) Override the doInBackground method to perform the query. Return the results. (Hint: You've already written the code to perform the query)
// TODO (3) Override onPostExecute to display the results in the TextView

MainActivity 에 inner class로 GithubQueryTask를 추가
GithubQueryTask의 doInBackground method에서 쿼리를 날리고 결과를 받는다.

GithubQueryTask의 onPostExecute method에서 가져온 결과를 TextView에 보여준다.


import android.os.AsyncTask;

...

     // TODO (1) Create a class called GithubQueryTask that extends AsyncTask<URL, Void, String>
    public class GithubQueryTask extends AsyncTask<URL, Void, String> {

        // TODO (2) Override the doInBackground method to perform the query. Return the results. (Hint: You've already written the code to perform the query)
        @Override
        protected String doInBackground(URL... params) {
            URL searchUrl = params[0];
            String githubSearchResults = null;
            try {
                githubSearchResults = NetworkUtils.getResponseFromHttpUrl(searchUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return githubSearchResults;
        }


        // TODO (3) Override onPostExecute to display the results in the TextView
        @Override
        protected void onPostExecute(String githubSearchResults) {
            if (githubSearchResults != null && !githubSearchResults.equals("")) {
                mSearchResultsTextView.setText(githubSearchResults);
            }
        }
    }


// TODO (4) Create a new GithubQueryTask and call its execute method, passing in the url to query

makeGithubSearchQuery 에서 쿼리를 날릴 때 변경한 GithubQueryTask를 사용하도록 한다.(기존것은 주석처리)

//        String githubSearchResults = null;
//        try {
//            githubSearchResults = NetworkUtils.getResponseFromHttpUrl(githubSearchUrl);
//            mSearchResultsTextView.setText(githubSearchResults);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
        // TODO (4) Create a new GithubQueryTask and call its execute method, passing in the url to query
        new GithubQueryTask().execute(githubSearchUrl); 


App을 실행시켜서 'queen'이라는 단어로 쿼리를 날리면

먼저 url을 화면에 보여주고 잠시 후에 쿼리 결과가 나타난다.


네트워크를 통한 요청을 했을 때 응답을 받을 때까지 대기하도록 해야하기 때문임.

응답받기전에 결과를 처리하려고 한 T02.04는 에러가 날 수 밖에 없음.

728x90
728x90

이번에는 네트워크를 통하여

github 검색을 하는 것인데


이번 예제의 실행결과는 무조건 실패다.

solution project를 실행시켜도 app 에러가 난다.

다음예제인 T02.05에서 해결이 되는 것이니 TODO 설정을 제대로 한 뒤에 다음 강좌로 넘어가기 바란다.



<!--TODO (1) Add the INTERNET permission-->

AndroidManifest.xml 에 internet을 사용하는 권한 추가


// TODO (2) Call getResponseFromHttpUrl and display the results in mSearchResultsTextView
// TODO (3) Surround the call to getResponseFromHttpUrl with a try / catch block to catch an IOException

MainActivity의 makeGithubSearchQuery method 에서 쿼리조회를 하고 결과를 가져온다.

network을 사용할 때 오류가 날 수 있으니 IOException으로 감싸준다.

import java.io.IOException;

...

     private void makeGithubSearchQuery() {
        String githubQuery = mSearchBoxEditText.getText().toString();
        URL githubSearchUrl = NetworkUtils.buildUrl(githubQuery);
        mUrlDisplayTextView.setText(githubSearchUrl.toString());

        // TODO (2) Call getResponseFromHttpUrl and display the results in mSearchResultsTextView
        // TODO (3) Surround the call to getResponseFromHttpUrl with a try / catch block to catch an IOException
        String githubSearchResults = null;
        try {
            githubSearchResults = NetworkUtils.getResponseFromHttpUrl(githubSearchUrl);
            mSearchResultsTextView.setText(githubSearchResults);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


---

실행시켜보면 앱이 바로 종료된다.

Lotcat에서 확인해보면

 2019-01-13 13:22:41.295 3960-3960/com.example.android.datafrominternet E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.android.datafrominternet, PID: 3960
    android.os.NetworkOnMainThreadException
        at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1448)
        at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:102)
        at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)
        at java.net.InetAddress.getAllByName(InetAddress.java:787)
        at com.android.okhttp.Dns$1.lookup(Dns.java:39)
        at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175)
        at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141)
        at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:407)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:244)
        at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:210)
        at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(Unknown Source:0)
        at com.example.android.datafrominternet.utilities.NetworkUtils.getResponseFromHttpUrl(NetworkUtils.java:76)
        at com.example.android.datafrominternet.MainActivity.makeGithubSearchQuery(MainActivity.java:63)
        at com.example.android.datafrominternet.MainActivity.onOptionsItemSelected(MainActivity.java:80)
        at android.app.Activity.onMenuItemSelected(Activity.java:3435)


로그는 거꾸 읽어가는 것임.

먼저 onMenuItemSelect에서 버튼클릭이 있어났고

onOptionsItemSelectd 에서 어떤버튼인지 확인한 다음.

makeGithubsearchQuery method 에서 NetworkUtils를 호출한다.

그 와중에 getInputStream 에서 최종 에러가 난 것이다.


위 에러가 나면 다음강좌로 넘어간다.

network 사용시에는 동기화라는 것이 필요한데 설정이 되어있지 않아서 발생하는 것임.

728x90
BLOG main image
"그게 뭐 어쨌다는 거냐?" 늘 누가 나에게 나에대한 말을할 때면 이말을 기억해라. by nobang

카테고리

nobang이야기 (1951)
Life With Gopro (7)
Life With Mini (79)
Diary (971)
너 그거 아니(do you know) (179)
난 그래 (159)
Study (290)
속지말자 (10)
Project (34)
Poem (15)
Song (0)
Photo (113)
낙서장 (45)
일정 (0)
C.A.P.i (2)
PodCast (0)
nobang (27)
고한친구들 (4)
recieve (0)
History (0)
android_app (2)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

Total :
Today : Yesterday :