본문 바로가기
개발

20221003_구글 포토에서 이미지 가져오기

by 이로서로 2022. 10. 3.

구글 포토에 업로드 되어 있는 이미지들을 가져다 쓰는 방법을 찾아보았습니다. 

저는 소프트웨어 개발자는 아니기에 정확하게 어떻게 구동되는 지는 모르겠지만 어떻게든 되게 만들어 보았습니다. 

 

크게는 아래와 같이 진행되는 것 같습니다. 

1. 구글 계정으로 로그인되게 만들기

1-1. 구글 클라우드에서 사용자 인증 정보 만들기. (Oauth2)

1-2. Firebase에서 프로젝트 추가

1-3. 로그인 하는 코드 추가

2. 구글 포토 api로 request보내고 결과 받아오기

 

 

1-1. 구글 클라우드에서 사용자 인증 정보 만들기. 

구글 클라우드를 가보면  아래와 같은 화면을 보실 수 있습니다. 

https://console.cloud.google.com/apis/credentials?project=river-data-741\

여기에서 화면 상단의 "사용자 인증 정보 만들기"를 클릭하고 OAuth 클라이언드 ID를 만들면 됩니다. 

 

여기서 제가 헤맸던 부분은 두가지 입니다. 

처음에는 API키로 만들어서 사용하려 해보았는데 작동을 하지 않았습니다. 아래와 같이 메세지가 나오더군요.

다음으로 OAuth로 시도를 하였습니다. 

OAuth로 진행할 때 SHA-1 인증서 디지털 지문을 요구하는데 뭔지를 모르겠었습니다. 인터넷에서 시도해보라는 걸 해봐도 password를 잘못넣었다고 나와서 제가 전에 했는데 비밀번호를 잘못 넣은 줄 알았습니다. 알고보니 이전에 한적이 없었더군요. keytool을 만드니 디지털 지문을 얻을 수 있었습니다.

https://docs.flutter.dev/deployment/android#signing-the-app
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ivory82&logNo=220162882132

 

1-2. Firebase 프로젝트 추가. 

OAuth 를 만들었으니 http를 이용해 google photo에서 정보를 얻을 수 있을 것 같았는데 당췌 어떻게 하는지 모르겠더군요. 이전에 파이썬으로 했을 때는 OAuth를 만들고 credential 파일만 넣어주면 작동해서 비슷할 거라고 생각했습니다. (똑같이 작동하는데 제가 방법을 못찾은 거일 수도 있겠죠? ) 왜인지 모르겠지만 아래와 같은 에러가 났었습니다. 

 

 

어떻게 찾은건지 모르겠지만 Firebase를 이용해 구글에 로그인 하면 어떻게든 되겠지라고 생각하고 Firebase에 기존에 있던 프로젝트를 연결하였습니다. 

당시에 참고 했던 링크 입니다. 따라하니 큰 문제 없이 됬습니다.

- https://firebase.google.com/docs/cli?hl=ko#install-cli-mac-linux 

- https://firebase.google.com/docs/flutter/setup?hl=ko&platform=ios 

 

1-3. 로그인 하는 코드 추가

로그인할 때는 이 링크를 참고했습니다. 

https://kanoos-stu.tistory.com/71

 

flutter 기본 project에서 floating button을 눌렀을 때 위 함수가 실행되게 하였더니 다른 앱처럼 구글 로그인 창이 뜨더군요!

 

 

2. 구글 포토 api로 request 보내고 결과 받아오기. 

이부분에서 또 헤맷습니다. 내공이 부족해서 api 문서만 읽고 코드를 작성할 수는 없었고, 다른 분들 자료를 찾아봐도 잘 되지는 않았습니다. 

결과적으로는 codelab의 예시 project에서 일부 코드를 따와서 되게 만들었습니다. 

- https://codelabs.developers.google.com/codelabs/google-photos-sharing?hl=ko#0 

git clone https://github.com/flutter/codelabs flutter-codelabs

이걸로 코드를 가져와서 들여다 보고 짜깁기했습니다. 특히나 photos_library_api_client.dart파일에서 "searchMediaItem" 함수를 참고 했습니다 .

Future<SearchMediaItemsResponse> searchMediaItems(
    SearchMediaItemsRequest request) async {
  final response = await http.post(
    Uri.parse('https://photoslibrary.googleapis.com/v1/mediaItems:search'),
    body: jsonEncode(request),
    headers: await _authHeaders,
  );

  printError(response);

  return SearchMediaItemsResponse.fromJson(
      jsonDecode(response.body) as Map<String, dynamic>);
}

 여기서는 _authHeader에 뭐가 들어가는지를 모르겠었습니다. codelab의 프로젝트에서는 이미 로그인이 되어 있고 client를 만들 때 _authHeaders를 넘겨주니 _authHeaders를 바로 쓸 수 있었는데, 저는 로그인하는 코드부터 다르게 짰으니 _authHeaders를 어디서 가져와야 하는지 모르겠었습니다. 코드를 보다가 client 생성할 때 받아오고, 그게 signin 했을 때 user한테서 나오는 걸 확인해서 코드를 짜깁기해낼 수 있었습니다. 

 

Future<UserCredential> signInWithGoogle() async {
  // Trigger the authentication flow
  // final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
  _currentUser = await GoogleSignIn(scopes: <String>[
    'profile',
    'https://www.googleapis.com/auth/photoslibrary',
    'https://www.googleapis.com/auth/photoslibrary.sharing'
  ]).signIn();

  // Obtain the auth details from the request
  final GoogleSignInAuthentication? googleAuth = await _currentUser?.authentication;

  // Create a new credential
  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth?.accessToken,
    idToken: googleAuth?.idToken,
  );

  // Once signed in, return the UserCredential
  return await FirebaseAuth.instance.signInWithCredential(credential);
}

signIn할 때의 정보를 _currentUser로 받아놓았습니다. 

 

  Future<String> testPhoto() async {
  // Get the filename of the image
  var request = {};
  request['pageSize'] = 100;
  // request['pageToken'] = "1";
  var request_json = json.encode(request);

  final response = await http.post(
    Uri.parse("https://photoslibrary.googleapis.com/v1/mediaItems:search"),
    body : request_json,
    headers: await _currentUser!.authHeaders,
  );

  List<String> responseToString = json.decode(response.body)['mediaItems'].toString().split(',');
  List<String> links = [];
  for(int i = 0; i< responseToString.length; i++){
    if( responseToString[i].contains("https://lh3.googleusercontent.com/")){
      links.add(responseToString[i]);
    }
    }
  return response.body;
}

API에 reques를 할 때 _currentUser.authHeaders를 headers로 넘겨주었습니다. 

이렇게 하니 response에 제 구글 포토에 저장된 사진들이 받아졌습니다. 

 

 

지금은 어떻게 구현되는지 확인하려고 project를 따로 만들어서 실험해보았는데, 나중에 merge할 때도 까먹고 고생할 것 같네요. ^^;

'개발' 카테고리의 다른 글

20221021_flutter animation 만들기  (0) 2022.10.21
20221018_개발 진행 상황  (0) 2022.10.18
20221008_구글 포토 API로 이미지 링크 가져오기  (0) 2022.10.09
20220917-일한 시간 분석 개선  (0) 2022.09.27
하고 싶은 일  (0) 2022.09.25

댓글