본문 바로가기
안드로이드 자바

[JAVA][Android] 네이버 회원 프로필 조회 API 사용하기

by teamnova 2024. 6. 2.
728x90

안녕하세요.

오늘은 네이버 회원 프로필 조회 API를 사용해서 네이버 계정에 설정되어 있는 프로필 사진과 닉네임을 가져와보겠습니다.

 

이를 위해서는 네이버 로그인 API를 사용해서 액세스 토큰을 가져와야 하는데요.

자세한 방법은 다음 글을 참고해주세요.

2024.05.15 - [안드로이드 자바] - [JAVA][Android] 네이버 로그인 API 사용하기

 

[JAVA][Android] 네이버 로그인 API 사용하기

안녕하세요.오늘은 네이버 로그인 API를 사용하는 예제를 진행해보겠습니다. 1. Naver Developers 설정https://developers.naver.com/apps/#/list 애플리케이션 - NAVER Developers developers.naver.com 위 링크에 접속

stickode.tistory.com

 

 

1. 의존성 설정

이 예제에서는 Glide를 사용해서 프로필 사진을 이미지뷰에 띄워줄 것이기 때문에, 앱 수준의 build.gradle 에 의존성을 추가해주겠습니다.

implementation 'com.github.bumptech.glide:glide:4.11.0'

 

 

2. 레이아웃 수정

api를 통해서 받아온 닉네임과 프로필 사진을 화면에 띄우기 위한 텍스트뷰와 이미지뷰를 다음과 같이 메인 액티비티 레이아웃에 추가합니다.

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/iv_profile"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="100dp"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/baseline_person_24" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="닉네임"
        android:visibility="invisible"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/iv_profile" />

    <com.navercorp.nid.oauth.view.NidOAuthLoginButton
        android:id="@+id/btn_login"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginBottom="50dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

3. 메인 액티비티 수정

 

다음은 네아로api를 통해 획득한 액세스 토큰을 이용해 회원 프로필 조회 api에 요청하여 닉네임과 프로필 사진을 받아오는 코드입니다.

 

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.bumptech.glide.Glide;
import com.navercorp.nid.NaverIdLoginSDK;
import com.navercorp.nid.oauth.OAuthLoginCallback;
import com.navercorp.nid.oauth.view.NidOAuthLoginButton;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {

    private ImageView ivProfile;
    private TextView tvName;
    private NidOAuthLoginButton btnLogin;
    private ExecutorService executorService;

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

        //뷰 객체 연결
        ivProfile = findViewById(R.id.iv_profile);
        tvName = findViewById(R.id.tv_name);
        btnLogin = findViewById(R.id.btn_login);

        //네아로 객체 초기화
        NaverIdLoginSDK.INSTANCE.initialize(this, getString(R.string.naver_client_id),
                getString(R.string.naver_client_secret), getString(R.string.app_name));

        // ExecutorService 초기화
        executorService = Executors.newSingleThreadExecutor();

        btnLogin.setOAuthLogin(new OAuthLoginCallback() {
            @Override
            public void onSuccess() {
                // 로그인 성공시 액세스 토큰 가져오기
                String accessToken = NaverIdLoginSDK.INSTANCE.getAccessToken();
                // 네트워크 작업을 별도의 스레드에서 수행
                executorService.execute(() -> {
                    String responseBody = getUserProfile(accessToken);
                    Log.i("프로필 가져오기", responseBody);

                    if (responseBody != null && !responseBody.isEmpty()) {
                        runOnUiThread(() -> updateUI(responseBody));
                    }
                });
            }

            @Override
            public void onFailure(int httpStatus, @NonNull String message) {
                // 통신 오류
                Log.e("네아로", "onFailure: httpStatus - " + httpStatus + " / message - " + message);
            }

            @Override
            public void onError(int errorCode, @NonNull String message) {
                // 네이버 로그인 중 오류 발생
                Log.e("네아로", "onError: errorCode - " + errorCode + " / message - " + message);
            }
        });
    }

    private String getUserProfile(String accessToken) {
        String apiURL = "https://openapi.naver.com/v1/nid/me";
        String authorization = "Bearer " + accessToken; // Bearer 다음에 공백 추가

        HttpURLConnection con = connect(apiURL);
        try {
            con.setRequestMethod("GET");
            con.setRequestProperty("Authorization", authorization);

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
                return readBody(con.getInputStream());
            } else { // 에러 발생
                return readBody(con.getErrorStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }

    private HttpURLConnection connect(String apiUrl){
        try {
            URL url = new URL(apiUrl);
            return (HttpURLConnection)url.openConnection();
        } catch (MalformedURLException e) {
            throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
        } catch (IOException e) {
            throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
        }
    }

    private String readBody(InputStream body){
        InputStreamReader streamReader = new InputStreamReader(body);


        try (BufferedReader lineReader = new BufferedReader(streamReader)) {
            StringBuilder responseBody = new StringBuilder();

            String line;
            while ((line = lineReader.readLine()) != null) {
                responseBody.append(line);
            }

            return responseBody.toString();
        } catch (IOException e) {
            throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e);
        }
    }

    private void updateUI(String responseBody) {
        try {
            JSONObject jsonObject = new JSONObject(responseBody);
            JSONObject response = jsonObject.getJSONObject("response");
            String name = response.getString("nickname");
            String profileImage = response.getString("profile_image");

            tvName.setText(name);
            if (profileImage != null && !profileImage.isEmpty()) {
                Glide.with(this).load(profileImage).into(ivProfile);
            }
            
            tvName.setVisibility(View.VISIBLE);
            ivProfile.setVisibility(View.VISIBLE);

            // 로그인 버튼 숨기기
            btnLogin.setVisibility(View.GONE);
        } catch (JSONException e) {
            Log.e("네아로", "JSON 파싱 오류", e);
        }
    }
}

 

 

4. 시연 영상