Privacy Policy

Hyeongpil built the 실력 측정기: 오버워치 app as an Ad Supported app. This SERVICE is provided by Hyeongpil at no cost and is intended for use as is.

This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.

If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at 실력 측정기: 오버워치 unless otherwise defined in this Privacy Policy.

Information Collection and Use

For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information, including but not limited to Android Ad ID. The information that I request will be retained on your device and is not collected by me in any way.

The app does use third party services that may collect information used to identify you.

Link to privacy policy of third party service providers used by the app

Log Data

I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.

Cookies

Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.

This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.

Service Providers

I may employ third-party companies and individuals due to the following reasons:

  • To facilitate our Service;
  • To provide the Service on our behalf;
  • To perform Service-related services; or
  • To assist us in analyzing how our Service is used.

I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.

Security

I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.

Links to Other Sites

This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.

Children’s Privacy

These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions.

Changes to This Privacy Policy

I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page.

Contact Us

If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me at chlgudvlf@gmail.com.

안녕하세요!


오늘은 제가 삽질했던 오류 해결법을 올려드리려고 합니다


ZipException은 Gradle에서 라이브러리를 추가할 때 가끔 발생하는 오류인데요


라이브러리 안에 같은 모듈이 중복되어 생기는 오류입니다.

보통 서드파티 라이브러리에서 구글 gms 등을 포함하여 충돌나는 경우가 많습니다.


다음과 같이 해결할 수 있습니다!


compile ('패키지 이름'){
exclude group: 'com.google.android.gms'
}


이렇게 하면 해당하는 패키지에 gms를 제외하고 컴파일되게 되어 충돌을 막을 수 있습니다.


하지만 저는 특수한 케이스에 부딪혔습니다!

기존 앱에 '파이어베이스'를 연동한 상태에서 '구글 플레이 게임' 을 연동하기 위해

BaseGameUtils를 모듈로 추가했었는데요


이때 zip exception com/google/android/gms/internal/z~~~.class 오류가 발생되어 고통을 받았었습니다.

이 해결법을 알려드리겠습니다!!


build.gradle(Module: BaseGameUtils) 에는 다음과 같이 선언되어있습니다.

if (!project.hasProperty('gms_library_version')) {
ext.gms_library_version = '8.4.0'
}
compile "com.google.android.gms:play-services-games:${gms_library_version}"
compile "com.google.android.gms:play-services-plus:${gms_library_version}"


제 build.gradle(Module: app) 에는 파이어베이스가 다음과 같이 선언되어 있었습니다.

compile 'com.google.firebase:firebase-core:10.0.1'
compile 'com.google.firebase:firebase-ads:10.0.1'


여기서 app의 파이어베이스에도 gms가 포함되어있었고, BaseGameUtils에도 gms가 포함되어 충돌이 일어났었는데요!

모듈이 달라 디버깅하기 쉽지 않았었습니다...

따라서 다음과 같이

compile "com.google.android.gms:play-services-games:10.0.1"
compile "com.google.android.gms:play-services-plus:10.0.1"

build.gradle(Module: BaseGameUtils) 의 버전을 맞춰주시면 아름답게 컴파일 되는 것을 확인할 수 있습니다!


저와 같은 고통을 받지 않으셨으면 좋겠습니다.


감사합니다!



안녕하세요!


안드로이드 앱을 개발하다보면 서버와의 통신 작업이 많이 필요하게 되는데요

이때 정말 편하게 사용할 수 있는 라이브러리인 Retrofit을 소개해보려고 합니다.


이 글을 작성할 때 

생각자유의 안드로이드 이야기 - Retrofit 기본 기능에 대해서 알아보자 

http://goo.gl/fOumEV

이 글을 많이 참조하였습니다!


http://square.github.io/retrofit/


저는 Retrofit을 이용하여 날씨 정보를 가져오는 API 통신을 해보겠습니다.

https://developers.skplanetx.com/apidoc/kor/weather/

SKplanet 에서 제공하는 Weather Planet에서 정보를 받아오겠습니다.


먼저 build.gradle(Module : app) 에 다음과 같이 추가해줍니다.

dependencies {
compile 'com.squareup.retrofit2:retrofit:2.1.0' // Retrofit
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3' // Gson 변환을 위한 converter
}


인터넷 통신을 하기 위해 퍼미션을 추가 해 줍니다.

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


이로써 Retrofit 을 사용하기 위한 준비가 끝났습니다.

이제 본격적으로 날씨 정보 얻어오기를 달려보겠습니다!


저는 현재날씨(시간별) 데이터를 받아보겠습니다.

Weather Planet 의 현재 날씨 API는 다음과 같은 양식으로 되어있습니다.

Resource URI

http://apis.skplanetx.com/weather/current/hourly?version={version}&lat={lat}&lon={lon}&city={city}&county={county}&village={village}

Protocol - REST

HTTP Method - GET


여기서 

http://apis.skplanetx.com/ 은 baseURL

weather/current/hourly 는 현재날씨(시간별)에 해당하는 URL

? 뒤쪽 부분은 변수 명이 됩니다.


이를 이용하여 Interface Class를 선언해 보겠습니다

저는 WeatherRepo 클래스 안에 인터페이스를 선언하여 Call<WeatherRepo> 로 나오게 되었습니다.

WeatherRepo 클래스는 API 통신을 하며 데이터를 받는 객체 클래스로 아래에서 설명드리겠습니다.

버전 정보와 위도, 경도만 필요하기 때문에 country 와 village는 생략하였습니다.

public interface WeatherApiInterface {
@Headers({"Accept: application/json"})
@GET("weather/current/hourly")
Call<WeatherRepo> get_Weather_retrofit(@Query("version") int version, @Query("lat") String lat, @Query("lon") String lon);
}

이와 같이

@Headers 에는 필요한 헤더 부분을 ({ ~~ . ~~ }) 형식으로 넣어줄 수 있습니다.

@GET 부분에는 현재날씨(시간별)에 해당하는 URL 을 넣어줍니다.

다음으로 Call입니다.

Call <'주고받을 객체'> '함수명' (@Query ('변수 이름') '자료형' '변수 이름')  형태로 나타나 있는데요

@Query 를 통해 위치가 바뀌어도 동적으로 값을 받아올 수 있습니다!


다음으로는 응답 샘플 코드를 보겠습니다.

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
{
    "result":{
        "message":"성공",
        "code":9200,
        "requestUrl":"/weather/current/hourly?lon=&village=도곡동&county=강남구&lat=&city=서울&version=1"
    },
    "common":{
        "alertYn":"Y",
        "stormYn":"N"
    },
    "weather":{
        "hourly":[
            {
                "grid":{
                    "latitude":"37.4870600000",
                    "longitude":"127.0460400000",
                    "city":"서울",
                    "county":"강남구",
                    "village":"도곡동"
                },
                "wind":{
                    "wdir":"266.00",
                    "wspd":"3.20"
                },
                "precipitation":{
                    "type":"0",
                    "sinceOntime":"0.00"
                },
                "sky":{
                    "name":"맑음",
                    "code":"SKY_O01"
                },
                "temperature":{
                    "tc":"6.80",
                    "tmax":"8.10",
                    "tmin":"-0.90"
                },
                "humidity":"31.00",
                "lightning":"0",
                "timeRelease":"2013-11-11 14:00:00"
            }
        ]
    }
}
cs


여기서 저희는 필요한 것만 골라서 받아올 수 있습니다!

갓 구글께서는 JSON을 쉽게 파싱할 수 있도록 GSON 라이브러리를 만들어 주셨습니다.

이를 야무지게 사용해 보겠습니다.


public class WeatherRepo {

@SerializedName("result")
Result result;
@SerializedName("weather")
weather weather;

public class Result {
@SerializedName("message") String message;
@SerializedName("code") String code;

public String getMessage() {return message;}
public String getCode() {return code;}
}

public class weather {

public List<hourly> hourly = new ArrayList<>();
public List<hourly> getHourly() {return hourly;}

public class hourly {
@SerializedName("sky") Sky sky;
@SerializedName("precipitation") precipitation precipitation;
@SerializedName("temperature") temperature temperature;
@SerializedName("wind") wind wind;

public class Sky{
@SerializedName("name") String name;
@SerializedName("code") String code;

public String getName() {return name;}
public String getCode() {return code;}
}

public class precipitation{ // 강수 정보
@SerializedName("sinceOntime") String sinceOntime; // 강우
@SerializedName("type") String type; //0 :없음 1:비 2: 비/눈 3: 눈

public String getSinceOntime() {return sinceOntime;}
public String getType() {return type;}
}
public class temperature{
@SerializedName("tc") String tc; // 현재 기온

public String getTc() {return tc;}
}
public class wind{ // 바람
@SerializedName("wdir") String wdir;
@SerializedName("wspd") String wspd;

public String getWdir() {return wdir;}
public String getWspd() {return wspd;}
}
public Sky getSky() {return sky;}
public hourly.precipitation getPrecipitation() {return precipitation;}
public hourly.temperature getTemperature() {return temperature;}
public hourly.wind getWind() {return wind;}
}
}
public Result getResult() {return result;}
public weather getWeather() {return weather;}

public interface WeatherApiInterface {
@Headers({"Accept: application/json"})
@GET("weather/current/hourly")
Call<WeatherRepo> get_Weather_retrofit(@Query("version") int version, @Query("lat") String lat, @Query("lon") String lon);
}
}

위의 응답 데이터 양식과 아래의 코드를 보면 

GSON이 쉽고 편하고 아름답게 파싱해 주는 것을 볼 수 있습니다!

여기서 @SerializedName 어노테이션이 포인트인데요

이 어노테이션을 이용하면 wspd(풍속) 을 

@SerializedName("wspd") String windSpeed; 처럼 변수 이름을 바꿔 넣을 수도 있습니다.


응답코드에 hourly 뒤를 보시면 JSONArray 형태로 되어 있는데요

이를 위와 같이 클래스로 만들어 ArrayList<hourly> 형태로 만들어준다면 쉽게 파싱이 가능합니다!

이부분을 잘 몰라서 삽질 했던 기억이 나네요...


다음으로는 위에서 만든 Retrofit interface를 구현해보도록 하겠습니다!

저는 날씨 정보를 가져오는 스레드인

WeatherThread 에서 날씨 정보를 받아오겠습니다.


public class WeatherThread extends Thread {
final static String TAG = "WeatherThread";
Context mContext;
WeatherRepo weatherRepo;
Handler handler;

int version = 1;
String lat;
String lon;

public WeatherThread(Handler handler, Context mContext, double lat, double lon) {
this.mContext = mContext;
this.lat = String. valueOf(lat);
this.lon = String .valueOf(lon);
this.handler = handler;
}

@Override
public void run() {
super.run();
Retrofit client = new Retrofit.Builder().baseUrl("http://apis.skplanetx.com/").addConverterFactory(GsonConverterFactory.create()).build();
WeatherRepo.WeatherApiInterface service = client.create(WeatherRepo.WeatherApiInterface.class);
Call<WeatherRepo> call = service.get_Weather_retrofit(version, lat, lon);
call.enqueue(new Callback<WeatherRepo>() {
@Override
public void onResponse(Call<WeatherRepo> call, Response<WeatherRepo> response) {
if(response.isSuccessful()){
weatherRepo = response.body();
Log.d(TAG,"response.raw :"+response.raw());
if(weatherRepo.getResult().getCode().equals("9200")){ // 9200 = 성공
Weather.getInstance().setTemperature(weatherRepo.getWeather().getHourly().get(0).getTemperature().getTc());
Weather.getInstance().setCloud(weatherRepo.getWeather().getHourly().get(0).getSky().getName());
Weather.getInstance().setWind_direction(weatherRepo.getWeather().getHourly().get(0).getWind().getWdir());
Weather.getInstance().setWind_speed(weatherRepo.getWeather().getHourly().get(0).getWind().getWspd());
Weather.getInstance().setIcon(weatherRepo.getWeather().getHourly().get(0).getSky().getCode());

Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("weather","weather");
msg.setData(bundle);
handler.sendMessage(msg);
}else{
Log.e(TAG,"요청 실패 :"+weatherRepo.getResult().getCode());
Log.e(TAG,"메시지 :"+weatherRepo.getResult().getMessage());
}
}
}

@Override
public void onFailure(Call<WeatherRepo> call, Throwable t) {
Log.e(TAG,"날씨정보 불러오기 실패 :" + t.getMessage() );
Log.e(TAG,"요청 메시지 :"+call.request());
}
});
}
}

생성자를 통해 위도와 경도를 받아와 

service.get_Weather_retrofit(version, lat, lon) 부분에 값을 넣어줍니다.

요청이 성공적으로 수행되면 onResponse로 진입을 하게 되는데 이곳에서 response.isSuccessful() 로 요청이 성공적으로 이루어 지면

WeatherRepo 에 response.body를 입혀줍니다. response.body 에는 위의 응답 샘플 코드와 같은 정보가 들어있어 이를 

GSON으로 파싱 할 수 있을 것입니다.

response.raw 함수로 응답으로 온 http raw 데이터를 볼 수 있습니다.

응답코드가 정상인지 확인한 후 

weatherRepo.get~~~ 함수들로 값을 받아와 객체에 저장할 수 있습니다!


Retrofit은 제가 사용한 GET 방법 외에도 POST, PUT 등 다양한 Request 방식을 지원합니다.

여러가지 사용법은 추후 공부를 더 하게되면 추가 해 나가도록 하겠습니다!


이상 Retrofit 사용법 글을 마치겠습니다 감사합니다!




안녕하세요! 


오늘도 삽질로 고통받았습니다... 안드로이드가 쉽지가 않네요.


예전에 카카오톡 로그인때문에 고통받았던 제 모습이 생각나서


고통을 조금이라도 일찍 해소해 드리기 위해


쉬지않고 바로 포스팅 달려보도록 하겠습니다!




카카오 로그인을 위해서는 KakaoSDKAdapter 가 있어야 합니다.


고수분들은 필요한것만 골라서 오버라이딩 해서 쓰는것으로 예상되지만 저는 아직 잘 모르기에


통짜로 복붙했습니다.. 허허


package com.example.hp.ee;

/**
* Created by hp on 2016-01-26.
*/

import android.app.Activity;
import android.content.Context;

import com.kakao.auth.ApprovalType;
import com.kakao.auth.AuthType;
import com.kakao.auth.IApplicationConfig;
import com.kakao.auth.ISessionConfig;
import com.kakao.auth.KakaoAdapter;

/**
* @author leoshin on 15. 9. 15.
*/
public class KakaoSDKAdapter extends KakaoAdapter {

/**
* Session Config에 대해서는 default값들이 존재한다.
* 필요한 상황에서만 override해서 사용하면 됨.
* @return Session의 설정값.
*/
@Override
public ISessionConfig getSessionConfig() {
return new ISessionConfig() {
@Override
public AuthType[] getAuthTypes() {
return new AuthType[] {AuthType.KAKAO_LOGIN_ALL};
}

@Override
public boolean isUsingWebviewTimer() {
return false;
}

@Override
public ApprovalType getApprovalType() {
return ApprovalType.INDIVIDUAL;
}

@Override
public boolean isSaveFormData() {
return true;
}
};
}

@Override
public IApplicationConfig getApplicationConfig() {
return new IApplicationConfig() {
@Override
public Activity getTopActivity() {
return GlobalApplication.getCurrentActivity();
}

@Override
public Context getApplicationContext() {
return GlobalApplication.getGlobalApplicationContext();
}
};
}
}
 

다음과 같이 KakaoSDKAdapter 를 만들어주면 GlobalApplication 에 빨간 밑줄이 그어져 있을것입니다.


GlobalApplication 도 카카오 로그인에 필요하므로 추가해주어야 합니다.

/**
* Created by hp on 2016-01-26.
*/

import android.app.Activity;
import android.app.Application;

import com.kakao.auth.KakaoSDK;

/**
* 이미지를 캐시를 앱 수준에서 관리하기 위한 애플리케이션 객체이다.
* 로그인 기반 샘플앱에서 사용한다.
*
* @author MJ
*/
public class GlobalApplication extends Application {
private static volatile GlobalApplication instance = null;
private static volatile Activity currentActivity = null;

@Override
public void onCreate() {
super.onCreate();
instance = this;

KakaoSDK.init(new KakaoSDKAdapter());
}

public static Activity getCurrentActivity() {
return currentActivity;
}

public static void setCurrentActivity(Activity currentActivity) {
GlobalApplication.currentActivity = currentActivity;
}

/**
* singleton 애플리케이션 객체를 얻는다.
* @return singleton 애플리케이션 객체
*/
public static GlobalApplication getGlobalApplicationContext() {
if(instance == null)
throw new IllegalStateException("this application does not inherit com.kakao.GlobalApplication");
return instance;
}

/**
* 애플리케이션 종료시 singleton 어플리케이션 객체 초기화한다.
*/
@Override
public void onTerminate() {
super.onTerminate();
instance = null;
}
}
 


GlobalApplication을 AndroidManifest.xml에 다음과 같이 추가시켜줍니다.


<application
android:name=".GlobalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"

이 과정들이 끝나면 아름답게 로그인이 될것입니다!


로그인버튼에 ID값으로 onClick을 넣어주지 않아도 LoginButton이 알아서 로그인을 다 해줍니다.


허허 신기하네요... 좀 더 공부한다음 다시 깊게 파보겠습니다!



로그인을 했으면 로그인 한 유저의 정보값을 얻을 수 있는데요


이는 KakaoSignupActivity의 RequestMe()함수에서


protected void requestMe() {
UserManagement.requestMe(new MeResponseCallback() {
@Override
public void onFailure(ErrorResult errorResult) {
String message = "failed to get user info. msg=" + errorResult;
Logger.d(message);

ErrorCode result = ErrorCode.valueOf(errorResult.getErrorCode());
if (result == ErrorCode.CLIENT_ERROR_CODE) {
finish();
} else {
redirectLoginActivity();
}
}
@Override
public void onSessionClosed(ErrorResult errorResult) {
redirectLoginActivity();
}

@Override
public void onNotSignedUp() {
}

@Override
public void onSuccess(UserProfile userProfile) {
String kakaoID = String.valueOf(userProfile.getId()); // userProfile에서 ID값을 가져옴
String kakaoNickname = userProfile.getNickname(); // Nickname 값을 가져옴
Logger.d("UserProfile : " + userProfile);
redirectMainActivity(); // 로그인 성공시 MainActivity
}
});
}

다음과 같이 userProfile.get??() 로 가져올 수 있습니다!!


이거 찾으라 삽질했던 기억이 나네요 ㅋㅋㅋ 


이를 이용해서 DB에 정보를 넣을 수 있을것입니다.


추가적인 정보를 넣는 방법은 카카오 개발 가이드에 자세하게 나와있습니다.



앱 구현 인턴을 하면서 카카오 로그인 기능을 구현하기 위해 이것 저것 뜯어보며 


깨알같이 카카오 로그인을 구현하게 되었습니다.


비록 함수에 대한 설명은 없지만...  콜백에 대해서 더 공부를 하여 무슨 원리로 구동되는지


꼭 공부를 해서 다시 포스팅 해보도록 하겠습니다!


저와 같은 학생들에게 조금이나마 도움이 되었으면 좋겠습니다.



이상 카카오 로그인 포스팅을 끝내겠습니다.


감사합니다!



안녕하세요! 


어제에 이어서 오늘도 달려보겠습니다.


먼저 카카오SDK의 샘플 앱을 보겠습니다.


















안을 살펴보면 OnCreate 안에


1
2
callback = new SessionCallback();
Session.getCurrentSession().addCallback(callback);
cs


이 두가지 매우 중요한 함수들이 있습니다. 이 콜백을 꼭 선언해주어야 합니다.





저는 다음과 같이 LoginActivity 에서 MainActivity로 넘어가도록 구현해 보겠습니다.


LoginActivity의 코드는 다음과 같습니다.  이 코드들은 SampleLoginActivity 에서 얻을 수 있습니다.

package com.example.hp.ee;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import com.kakao.auth.ISessionCallback;
import com.kakao.auth.Session;
import com.kakao.util.exception.KakaoException;
import com.kakao.util.helper.log.Logger;

/**
* Created by hp on 2016-01-26.
*/
public class LoginActivity extends Activity {

private SessionCallback callback; //콜백 선언

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

callback = new SessionCallback(); // 이 두개의 함수 중요함
Session.getCurrentSession().addCallback(callback);

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (Session.getCurrentSession().handleActivityResult(requestCode, resultCode, data)) {
return;
}
super.onActivityResult(requestCode, resultCode, data);
}

@Override
protected void onDestroy() {
super.onDestroy();
Session.getCurrentSession().removeCallback(callback);
}

private class SessionCallback implements ISessionCallback {

@Override
public void onSessionOpened() {
redirectSignupActivity(); // 세션 연결성공 시 redirectSignupActivity() 호출
}

@Override
public void onSessionOpenFailed(KakaoException exception) {
if(exception != null) {
Logger.e(exception);
}
setContentView(R.layout.activity_login); // 세션 연결이 실패했을때
} // 로그인화면을 다시 불러옴
}

protected void redirectSignupActivity() { //세션 연결 성공 시 SignupActivity로 넘김
final Intent intent = new Intent(this, KakaoSignupActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
finish();
}

}


현재 구현중이신 LoginActivity 화면에 다음과 같은 코드를 넣어주시면 됩니다!


 

다음으로 kakaoSignupActivity를 보겠습니다.


다음과 같이 Activity를 만들어줍니다.


package com.example.hp.ee;

/**
* Created by hp on 2016-01-26.
*/

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import com.kakao.auth.ApiResponseCallback;
import com.kakao.auth.ErrorCode;
import com.kakao.network.ErrorResult;
import com.kakao.usermgmt.UserManagement;
import com.kakao.usermgmt.callback.MeResponseCallback;
import com.kakao.usermgmt.response.model.UserProfile;

import com.kakao.util.helper.log.Logger;

public class KakaoSignupActivity extends Activity{
/**
* Main으로 넘길지 가입 페이지를 그릴지 판단하기 위해 me를 호출한다.
* @param savedInstanceState 기존 session 정보가 저장된 객체
*/

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestMe();
}

/**
* 사용자의 상태를 알아 보기 위해 me API 호출을 한다.
*/
protected void requestMe() { //유저의 정보를 받아오는 함수
UserManagement.requestMe(new MeResponseCallback() {
@Override
public void onFailure(ErrorResult errorResult) {
String message = "failed to get user info. msg=" + errorResult;
Logger.d(message);

ErrorCode result = ErrorCode.valueOf(errorResult.getErrorCode());
if (result == ErrorCode.CLIENT_ERROR_CODE) {
finish();
} else {
redirectLoginActivity();
}
}

@Override
public void onSessionClosed(ErrorResult errorResult) {
redirectLoginActivity();
}

@Override
public void onNotSignedUp() {} // 카카오톡 회원이 아닐 시 showSignup(); 호출해야함

@Override
public void onSuccess(UserProfile userProfile) { //성공 시 userProfile 형태로 반환
Logger.d("UserProfile : " + userProfile);
redirectMainActivity(); // 로그인 성공시 MainActivity
}
});
}

private void redirectMainActivity() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
protected void redirectLoginActivity() {
final Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
finish();
}

}
 


다음으로 로그인 버튼을 만들어보겠습니다!


activity_login.xml 파일에 다음과 같은 코드를 추가합니다.


<com.kakao.usermgmt.LoginButton
android:id="@+id/com_kakao_login"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="30dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>




그럼 다음과 같은 친숙한 카카오 로그인 버튼을 볼 수 있습니다.


다음으로는 로그인을 위한 카카오 SDK 와 GlobalApplication 을 구현해보도록 하겠습니다!

안녕하세요! 


오늘은 제가 인턴을 하면서 삽질하며 구현한 ' 카카오톡 로그인 연동 '을 포스팅 해보겠습니다.


카카오 로그인은 https://developer.kakao.com/docs/android 

에 자세히 설명되어 있지만 안드로이드를 처음 만져봤던 저는 봐도 이해를 잘 하지 못했었습니다.


인터넷에서도 고수분들이 포스팅해서 다 알 수 없는 내용뿐들이었어요....



그래서 안드로이드를 처음 시작하는 초보자의 관점에서 이 글을 써보겠습니다!



저는 카카오 로그인 연동을 거의 샘플앱을 복붙해서 구현하였습니다.(ㅋㅋㅋ....)




먼저 안드로이드 스튜디오에 gradle을 이용해 kakao sdk를 추가해보겠습니다!


저는 http://shindowjy.tistory.com/148  

이 블로그를 참조했습니다.




 


build.gradle(Project: ) 에 다음과 같은 코드를 추가해줍니다.


1
2
3
4
5
6
7
allprojects { 
   repositories {    
     jcenter()       
     mavenCentral()       
   }
}
cs


gradle.properties에 다음과 같은 코드를 추가해줍니다.


KAKAO_SDK_GROUP=com.kakao.sdk

KAKAO_SDK_VERSION=1.1.7


버전에는 가장 최신버전의 sdk를 적어줍니다.


build.gladle(Module: )에 다음과 같은 코드를 추가해줍니다.

1
2
3
4
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile group: project.KAKAO_SDK_GROUP, name: 'usermgmt', version: project.KAKAO_SDK_VERSION
}
cs


3번째 줄에 name : 에는 원하는 모듈을 선택적으로 쓸 수 있습니다.


저는 로그인 기능을 구현하므로 usermgmt를 사용하였습니다.



다음으로 AndroidManifest.xml에 카카오 앱 키를 추가합니다.


1
2
<meta-data android:name="com.kakao.sdk.AppKey"    
android:value=" ~~~ " />
cs


앱 키를 받는 방법은 카카오 개발 가이드에 자세하게 나와있으므로 생략하겠습니다.


해시키를 구하는게 조금 귀찮을 수 있는데  가이드에 나온 방법을 사용하려면 open ssl 을 설치하여


환경변수를 설정해준 뒤 cmd에 명령어를 치면 해시키를 얻을 수 있습니다.




이로써 카카오 로그인 연동을 위한 모든 준비를 마쳤습니다!


다음 포스팅에서는 로그인 버튼을 만들고 세션을 얻어오는 방법에 대해 알아보겠습니다.


감사합니다!


+ Recent posts