Masahiro Okubo

Android JavaでGoogle Photos APIと繋げてデータを取ってみる

Android JavaでGoogle Photos APIと繋げてデータを取ってみる

JavaでAndroidアプリ作るのが初めてレベルですごく大変だったので、
手順とコードをまとめてみました

ネットにある程度情報は乗っていますが、
おそらくJavaの先輩方はあれでもわかるのかもしれんですけど
javascriptメインの僕にはきつかったので
Java新米の僕宛に書くつもりで書いてきます

コードはgitにアップしておきました
Photos APIとCredentialsが出来上がっていればすぐに使えるようになっているので、
参考にしてください

 

Android プロジェクトを作成

この内容で作成

 

Google Photos APIを登録する

 この辺りはネットで探せばすぐに出てくると思うのでこちらを参考にして
わからなければ探してみてください

Get started with Java client library

 

Credentialsを登録する

Credentialを作る
Credentialはandroidアプリ毎にpackage nameをつけないといけないので、
このプロジェクトでは「com.example.googlephotosapi」となっていますが、
自身のプロジェクトでOAuth認証を行いたい場合は自分のパッケージネームをいれてください

Credentialのタイプは「OAuth client ID」

 

 

これで完成

コード実装

app/bundle.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.googlephotosapi"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/ASL2.0'
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'com.squareup.okhttp3:okhttp:3.10.0'
    // Google Photos
    implementation 'com.google.photos.library:google-photos-library-client:1.1.0'
    // AUth関連をここでimportできる
    implementation 'com.google.android.gms:play-services-auth:15.0.1'
    // Google Credentials
    implementation('com.google.api-client:google-api-client-android:1.23.0') {
        exclude module: 'guava-jdk5'
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.googlephotosapi">


    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

MainActivity.java

package com.example.googlephotosapi;

import android.accounts.Account;
import android.content.Intent;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.Scope;

import java.io.IOException;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    private GoogleSignInAccount mGoogleSignInAccount = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                choseAccount();
            }
        });
    }

    public void choseAccount() {
        try {
            Scope mScope = new Scope("https://www.googleapis.com/auth/photoslibrary");
            GoogleSignInOptions gso = new GoogleSignInOptions
                    .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                    .requestScopes(mScope)
                    .requestEmail()
                    .build();
            GoogleApiClient mGoogleApiClient = new GoogleApiClient
                    .Builder(this)
                    .enableAutoManage(this, null)
                    .addScope(mScope)
                    .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                    .build();
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
            startActivityForResult(signInIntent, 1);
        } catch (Exception e) {
            Log.d("TAG",  e.getMessage());
        }
    }

    @Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (requestCode == 1) {
			GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                mGoogleSignInAccount = result.getSignInAccount();
            }
            if (mGoogleSignInAccount != null) {
                AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
                    @Override
                    protected String doInBackground(Void... params) {
                        String accessToken = null;
                        try {
                            accessToken = GoogleAuthUtil.getToken(
                                    MainActivity.this,
                                    new Account(mGoogleSignInAccount.getEmail(), GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE),
                                    "oauth2:https://www.googleapis.com/auth/photoslibrary");
                            Request request = new Request.Builder()
                                    .url("https://photoslibrary.googleapis.com/v1/mediaItems")
                                    .addHeader("Authorization", "Bearer " + accessToken)
                                    .build();
                            OkHttpClient client = new OkHttpClient();
                            Response response = null;
                            try {
                                response = client.newCall(request).execute();
                                String r = response.body().string();
                                Log.i("TAG", r);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        } catch (IOException transientEx) {
                            Log.e("TAG", transientEx.toString());
                        } catch (UserRecoverableAuthException e) {
                            Log.e("TAG", e.toString());
                        } catch (GoogleAuthException authEx) {
                            Log.e("TAG", authEx.toString());
                        }
                        return accessToken;
                    }
                    @Override
                    protected void onPostExecute(String token) {
                        Log.i("TAG", "Access token retrieved:" + token);
                    }
                };
                task.execute();
            }
		}
	}
}

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Google Photos API呼び出し"
        tools:layout_editor_absoluteX="95dp"
        tools:layout_editor_absoluteY="292dp" />

</android.support.constraint.ConstraintLayout>

検証

デバッグモードで実行していきます

デバッグのポイントをいくつかつけときます

デバッグスタート

ちょうどここで実機ではこのような画面が出てきます

Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);

 

選択画面が出てくるのでGoogle Photoに画像をいれている方を選びます

 

 

アカウントを選択するとデバッグが進みますのでここまで行くとGoogle Photosから
responseデータが帰ってきています!!!
ちょうど「r」のところです
この「r」の中身をしっかりとみるために下のVariablesのところから
「r」のある行の一番みぎにある「View」をクリックして中身を確かめます

よかったちゃんときてる!!
今回はアルバムデータではなく写真を取ってくるmedeiaItemsを指定していたので
このようなデータの型になってます

ここまでデータを取れればあとはこれを処理してやるだけなので簡単だと思います

 

終わりに

今回初めてまともにJava使ってみましたが、最初は長くてめんどくさかったけど
型がしっかりしているのでちゃんとエラー出してくれてすごく安心してできたなー
と最後には思いました
連結部分だけでしたがやはり新米には難しいと感じることが多々あったので、
この記事が誰かの役に立てれば幸いです!

GItのレポ

https://bitbucket.org/hiyashikyuri/google-photos-api/src/master/

参考記事 

Get started with Java client library

AndroidアプリでGoogle Photos APIsを使ってみた!!

Access google photos API via Java

/google-auth-library-java

AndroidのGoogleSignInAPIを使ってOAuth認証を行う

Androidの新しいGoogleサインインAPIについて

GoogleAuthUtilを使ってOAuth 2.0 tokenを取得する

“Calling this from your main thread can lead to deadlock and/or ANRs while getting accesToken” from GoogleAuthUtil(Google Plus integration in Android) 

Method: mediaItems.list


関連記事

copyright© 2016-2021 Masahiro Okubo