0
3

More than 3 years have passed since last update.

Google Photos APIsでフォトアルバム

Posted at

私は普段Android端末を使っており、奥さんと旅行などに行った際よく写真を撮ります。
アカウントの同期を行っている方は、Android端末で撮った写真が自動でGoogleのPhotosサーバにバックアップされると思います。
Google Photos APIsが公開され、Google Photosサーバから直接画像を取得出来るようになったため、これを利用してフォトアルバムを作ろうと思ったのが本記事のきっかけです。

はじめに

本記事では、Google Photos APIsを用いフォトアルバムを表示するWebアプリ(Spring-boot)を作成します。
ソースは、Git にあげております。
下図の様に指定期間範囲内に撮った画像を、指定の間隔で再生するよう実装しております。
sample1.png

スコープ

・Google Photos APIsの有効化
・認証情報の取得
・フォトアルバム Webアプリ開発

Google Photos APIsの有効化

公式の案内 Enable the API に従えば、3step程で有効化できます。

認証情報の取得

こちらも公式の案内 Request an OAuth 2.0 client ID が分かりやすく、こちらを参照すれば簡単に出来ます。
サンプルのソースでは、下記設定としております。
[Name]: OAuth client
[Authorized JavaScript origins]: http://localhost:8081
[Authorized redirect URIs]: http://localhost:8081/Callback

設定が完了したら、作成したOAuth 2.0 Client IDsのダウンロードボタンから認証ファイルを取得します。
WebサーバがGoogle Photos APIsを使用する際に必要となります。

フォトアルバム Webアプリ開発

認証

PhotosLibraryClientFactory.java
public static PhotosLibraryClient Client;

// ユーザーに手動で認証してもらうURL
public static String AuthUrl;

// [本記事]-[認証情報の取得]でダウンロードした認証ファイルのパス
public String mCredentialsPath;

public PhotosLibraryClientFactory(String credentialsPath) {
    this.mCredentialsPath = credentialsPath;
}

public boolean init() throws IOException, GeneralSecurityException {
    if(Client != null) return true;

    Credentials credentials = getUserCredentials();
    if(credentials == null) return false;

    PhotosLibrarySettings settings = PhotosLibrarySettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credentials))
            .build();

    Client = PhotosLibraryClient.initialize(settings);
    return true;
}

private Credentials getUserCredentials() throws IOException, GeneralSecurityException {
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(new FileInputStream(this.mCredentialsPath)));
    String clientId = clientSecrets.getDetails().getClientId();
    String clientSecret = clientSecrets.getDetails().getClientSecret();

    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
        GoogleNetHttpTransport.newTrustedTransport(),
        JSON_FACTORY,
        clientSecrets,
        ImmutableList.of("https://www.googleapis.com/auth/photoslibrary.readonly")
    )
        .setDataStoreFactory(new FileDataStoreFactory(DATA_STORE_DIR))
        .setAccessType("offline")
        .build();

    LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(LOCAL_RECEIVER_PORT).build();

    Credential credential = flow.loadCredential("user");
    if (credential != null && (
            credential.getRefreshToken() != null ||
            credential.getExpiresInSeconds() == null ||
            credential.getExpiresInSeconds() > 60)) {
        // 認証成功した場合は認証情報を返す
        return UserCredentials.newBuilder()
                .setClientId(clientId)
                .setClientSecret(clientSecret)
                .setRefreshToken(credential.getRefreshToken())
                .build();
    }

    // 手動で認証が必要な場合は、認証URLを取得する
    String redirectUri = receiver.getRedirectUri();
    AuthorizationCodeRequestUrl authorizationUrl = flow.newAuthorizationUrl().setRedirectUri(redirectUri);
    AuthUrl = authorizationUrl.build();
    return null;
}

手動での認証が必要な場合は、AuthUrl に認証URLを設定しています。
こちらはUI側で一度開き、ユーザーに手作業で認証作業を行ってもらう必要があります。

画像のURL取得

PhotosLibraryClientFactory.java
public static java.util.Date StartDate;
public static java.util.Date EndDate;

public Iterable<MediaItem> getPhotos() throws IOException, GeneralSecurityException {
    if(!init()) return null;

    Builder builder = SearchMediaItemsRequest.newBuilder();
    if(StartDate != null && EndDate != null) {
        DateFilter dateFilter = DateFilter.newBuilder().addRanges(DateRange.newBuilder()
                        .setStartDate(CommonUtils.convertToGoogleDate(StartDate))
                        .setEndDate(CommonUtils.convertToGoogleDate(EndDate)).build()).build();
        Filters filter = Filters.newBuilder().setDateFilter(dateFilter).build();
        builder.setFilters(filter);
    }

    SearchMediaItemsRequest request = builder.build();
    SearchMediaItemsResponse response = PhotosLibraryClientFactory.Client.searchMediaItemsCallable().call(request);
    return response.getMediaItemsList();
}

StartDateやEndDateが指定されていた場合、指定期間に撮った写真を検索します。
指定されていない場合は検索条件なしになりますが「このアルバムの画像を取得」のような検索の仕方も可能ですので、お好みの検索ロジックを組むと良いと思います。

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3