Naver OAuth 2.0 for Android
이미지 출처: https://developers.naver.com/docs/login/bi/
01. Naver OAuth 2.0 API 신청하기
https://developers.naver.com/apps/#/register?api=nvlogin
02. 라이브러리 및 샘플 프로젝트 다운로드
https://developers.naver.com/docs/login/sdks/
03. API 사용가이드 상세
https://developers.naver.com/docs/login/android/
04. 샘플 프로젝트 임포트 및 샘플코드 수정
package me.blog.korn123.android_cookbook_2017.naver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.beardedhen.androidbootstrap.TypefaceProvider;
import com.google.gson.Gson;
import com.nhn.android.naverlogin.OAuthLogin;
import com.nhn.android.naverlogin.OAuthLoginDefine;
import com.nhn.android.naverlogin.OAuthLoginHandler;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import me.blog.korn123.android_cookbook_2017.R;
/**
* Created by hanjoong on 2017-03-08.
* 네이버 개발자센터 제공 코드의 일부를 수정함.
*/
public class NaverLoginActivity extends AppCompatActivity {
private static Context mContext;
private static String OAUTH_CLIENT_ID = "QQxxxxxxxxxxxx";
private static String OAUTH_CLIENT_SECRET = "yTp5Gxxxxxxx";
private static String OAUTH_CLIENT_NAME = "네이버 아이디로 로그인";
private static OAuthLogin mOAuthLoginInstance;
private StringBuilder sb = new StringBuilder();
@BindView(R.id.accessToken)
TextView mAccessToken;
@BindView(R.id.refreshTokenView)
TextView mRefreshTokenView;
@BindView(R.id.type)
TextView mType;
@BindView(R.id.state)
TextView mState;
@BindView(R.id.userInfo)
TextView mUserInfo;
@BindView(R.id.profileImage)
ImageView mProfileImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TypefaceProvider.registerDefaultIconSets();
setContentView(R.layout.activity_naver_login);
ButterKnife.bind(this);
mContext = NaverLoginActivity.this;
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
OAuthLoginDefine.DEVELOPER_VERSION = true;
initData();
updateView();
}
/**
* startOAuthLoginActivity() 호출시 인자로 넘기거나, OAuthLoginButton 에 등록해주면 인증이 종료되는 걸 알 수 있다.
*/
private OAuthLoginHandler mOAuthLoginHandler = new OAuthLoginHandler() {
@Override
public void run(boolean success) {
if (success) {
updateView();
} else {
String errorCode = mOAuthLoginInstance.getLastErrorCode(mContext).getCode();
String errorDesc = mOAuthLoginInstance.getLastErrorDesc(mContext);
Toast.makeText(mContext, "errorCode:" + errorCode + ", errorDesc:" + errorDesc, Toast.LENGTH_SHORT).show();
}
};
};
private void initData() {
mOAuthLoginInstance = OAuthLogin.getInstance();
mOAuthLoginInstance.init(mContext, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CLIENT_NAME);
/*
* 2015년 8월 이전에 등록하고 앱 정보 갱신을 안한 경우 기존에 설정해준 callback intent url 을 넣어줘야 로그인하는데 문제가 안생긴다.
* 2015년 8월 이후에 등록했거나 그 뒤에 앱 정보 갱신을 하면서 package name 을 넣어준 경우 callback intent url 을 생략해도 된다.
*/
//mOAuthLoginInstance.init(mContext, OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET, OAUTH_CLIENT_NAME, OAUTH_callback_intent_url);
}
private void updateView() {
String accessToken = mOAuthLoginInstance.getAccessToken(mContext);
String refreshToken = mOAuthLoginInstance.getRefreshToken(mContext);
long expiresAt = mOAuthLoginInstance.getExpiresAt(mContext);
String tokenType = mOAuthLoginInstance.getTokenType(mContext);
mAccessToken.setText("accessToken: " + accessToken);
mRefreshTokenView.setText("refreshToken: " + refreshToken);
mType.setText("type: " + tokenType);
mState.setText("state: " + mOAuthLoginInstance.getState(mContext).toString());
getSupportActionBar().setTitle("Naver OAuth token 유효시간");
getSupportActionBar().setSubtitle(new Timestamp(expiresAt * 1000).toString());
clearProfile();
}
private void clearProfile() {
mUserInfo.setText((String) "");
sb.setLength(0);
mProfileImage.setImageResource(0);
}
public void executeTask(View view) {
int id = view.getId();
switch (id) {
case R.id.login:
mOAuthLoginInstance.startOauthLoginActivity(NaverLoginActivity.this, mOAuthLoginHandler);
break;
case R.id.requestUserInfo1:
new RequestApiTask().execute();
break;
case R.id.refreshToken:
new RefreshTokenTask().execute();
break;
case R.id.logout:
mOAuthLoginInstance.logout(mContext);
updateView();
break;
case R.id.deleteToken:
mOAuthLoginInstance.logoutAndDeleteToken(mContext);
updateView();
default:
break;
}
}
private class RefreshTokenTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
return mOAuthLoginInstance.refreshAccessToken(mContext);
}
protected void onPostExecute(String res) {
updateView();
}
}
private class RequestApiTask extends AsyncTask<Void, Void, Bitmap> {
@Override
protected void onPreExecute() {
clearProfile();
}
/**
* background thread에서 회원프로필 조회 후 프로필 이미지 생성
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(Void... params) { // separate thread
Bitmap profileImage = null;
String url = "https://openapi.naver.com/v1/nid/me";
String at = mOAuthLoginInstance.getAccessToken(mContext);
String jsonString = mOAuthLoginInstance.requestApi(mContext, at, url);
Map map = new Gson().fromJson(jsonString, HashMap.class);
if (map.get("resultcode").equals("00")) {
Map childMap = (Map)map.get("response");
String profileUrl = String.valueOf(childMap.get("profile_image"));
sb.append("message: " + map.get("message") + "\n");
sb.append("resultcode: " + map.get("resultcode")+ "\n");
sb.append("response.email: " + childMap.get("email") + "\n");
sb.append("response.nickname: " + childMap.get("nickname") + "\n");
sb.append("response.age: " + childMap.get("age") + "\n");
sb.append("response.gender: " + childMap.get("gender") + "\n");
sb.append("response.name: " + childMap.get("name") + "\n");
sb.append("response.birthday: " + childMap.get("birthday") + "\n");
profileImage = uriToBitmap(profileUrl);
} else {
makeSnackBar(findViewById(android.R.id.content), String.valueOf(map.get("message")));
}
return profileImage;
}
/**
* main thread에서 프로필 및 이미지를 업데이트
* @param profileImage
*/
protected void onPostExecute(Bitmap profileImage) { // main thread
mUserInfo.setText(sb.toString());
mProfileImage.setImageBitmap(profileImage);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
public void makeSnackBar(View view, String message) {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
public Bitmap uriToBitmap(String profileUrl) {
HttpURLConnection connection = null;
Bitmap bitmap = null;
try {
URL url = new URL(profileUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(input);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(connection!=null)connection.disconnect();
}
return bitmap;
}
}