Mengakses Google API dengan GoogleApiClient (tidak digunakan lagi)

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Anda dapat menggunakan objek GoogleApiClient ("Klien Google API") untuk mengakses Google API yang disediakan di library layanan Google Play (seperti Login dengan Google, Game, dan Drive). Klien Google API menyediakan titik entri umum ke layanan Google Play dan mengelola koneksi jaringan antara perangkat pengguna dan setiap layanan Google.

Namun, antarmuka GoogleApi yang lebih baru dan implementasinya lebih mudah digunakan dan merupakan cara yang lebih disukai untuk mengakses API layanan Play. Lihat Mengakses Google API.

Panduan ini menunjukkan cara:

  • Mengelola koneksi Anda ke layanan Google Play secara otomatis.
  • Melakukan panggilan API sinkron dan asinkron ke semua layanan Google Play.
  • Kelola koneksi Anda ke layanan Google Play secara manual dalam kasus yang jarang terjadi jika hal ini diperlukan. Untuk mempelajari lebih lanjut, lihat Koneksi yang dikelola secara manual.
Gambar 1: Ilustrasi yang menunjukkan cara Klien Google API menyediakan antarmuka untuk menghubungkan dan melakukan panggilan ke salah satu layanan Google Play yang tersedia seperti Google Play Game dan Google Drive.

Untuk memulai, Anda harus menginstal library layanan Google Play terlebih dahulu (revisi 15 atau yang lebih tinggi) untuk Android SDK Anda. Jika Anda belum melakukannya, ikuti petunjuk di Menyiapkan SDK Layanan Google Play.

Memulai koneksi yang dikelola secara otomatis

Setelah project Anda ditautkan ke library layanan Google Play, buat instance GoogleApiClient menggunakan GoogleApiClient.Builder API dalam metode onCreate() aktivitas Anda. Class GoogleApiClient.Builder menyediakan metode yang memungkinkan Anda menentukan Google API yang ingin digunakan dan cakupan OAuth 2.0 yang diinginkan. Berikut adalah contoh kode yang membuat instance GoogleApiClient yang terhubung dengan layanan Google Drive:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Drive.API)
    .addScope(Drive.SCOPE_FILE)
    .build();

Anda dapat menambahkan beberapa API dan beberapa cakupan ke GoogleApiClient yang sama dengan menambahkan panggilan tambahan ke addApi() dan addScope().

Penting: Jika menambahkan Wearable API bersama API lain ke GoogleApiClient, Anda mungkin mengalami error koneksi klien pada perangkat yang tidak menginstal aplikasi Wear OS. Untuk menghindari error koneksi, panggil metode addApiIfAvailable() dan teruskan Wearable API agar klien Anda dapat menangani API yang hilang dengan baik. Untuk informasi selengkapnya, lihat Mengakses Wearable API.

Untuk memulai koneksi yang dikelola secara otomatis, Anda harus menentukan implementasi antarmuka OnConnectionFailedListener untuk menerima error koneksi yang tidak dapat diselesaikan. Saat instance GoogleApiClient yang dikelola secara otomatis mencoba terhubung ke Google API, instance akan otomatis menampilkan UI untuk mencoba memperbaiki kegagalan koneksi yang dapat diselesaikan (misalnya, jika layanan Google Play perlu diperbarui). Jika terjadi error yang tidak dapat diselesaikan, Anda akan menerima panggilan ke onConnectionFailed().

Anda juga dapat menentukan implementasi opsional untuk antarmuka ConnectionCallbacks jika aplikasi perlu mengetahui kapan koneksi yang dikelola secara otomatis dibuat atau ditangguhkan. Misalnya, jika aplikasi Anda melakukan panggilan untuk menulis data ke Google API, panggilan tersebut hanya boleh dipanggil setelah metode onConnected() dipanggil.

Berikut adalah contoh aktivitas yang mengimplementasikan antarmuka callback dan menambahkannya ke Klien Google API:

import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import gms.drive.*;
import android.support.v4.app.FragmentActivity;

public class MyActivity extends FragmentActivity
        implements OnConnectionFailedListener {
    private GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Create a GoogleApiClient instance
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this /* FragmentActivity */,
                                  this /* OnConnectionFailedListener */)
                .addApi(Drive.API)
                .addScope(Drive.SCOPE_FILE)
                .build();

        // ...
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // An unresolvable error has occurred and a connection to Google APIs
        // could not be established. Display an error message, or handle
        // the failure silently

        // ...
    }
}

Instance GoogleApiClient akan otomatis terhubung setelah aktivitas Anda memanggil onStart() dan memutuskan koneksi setelah memanggil onStop(). Aplikasi Anda dapat segera mulai membuat permintaan baca ke Google API setelah mem-build GoogleApiClient, tanpa menunggu koneksi selesai.

Berkomunikasi dengan Layanan Google

Setelah terhubung, klien Anda dapat melakukan panggilan baca dan tulis menggunakan API khusus layanan yang diotorisasi oleh aplikasi Anda, seperti yang ditentukan oleh API dan cakupan yang Anda tambahkan ke instance GoogleApiClient.

Catatan: Sebelum melakukan panggilan ke layanan Google tertentu, Anda mungkin harus mendaftarkan aplikasi terlebih dahulu di Google Developer Console. Untuk mendapatkan petunjuk, lihat panduan memulai yang sesuai untuk API yang Anda gunakan, seperti Google Drive atau Login dengan Google.

Saat Anda membuat permintaan baca atau tulis menggunakan GoogleApiClient, klien API akan menampilkan objek PendingResult yang mewakili permintaan. Hal ini terjadi segera, sebelum permintaan dikirim ke layanan Google yang dipanggil oleh aplikasi Anda.

Misalnya, berikut adalah permintaan untuk membaca file dari Google Drive yang menyediakan objek PendingResult:

Query query = new Query.Builder()
        .addFilter(Filters.eq(SearchableField.TITLE, filename));
PendingResult<DriveApi.MetadataBufferResult> result = Drive.DriveApi.query(mGoogleApiClient, query);

Setelah memiliki objek PendingResult, aplikasi Anda kemudian dapat menentukan apakah permintaan ditangani sebagai panggilan asinkron atau sebagai panggilan sinkron.

Tips: Aplikasi Anda dapat mengantrekan permintaan baca tanpa terhubung ke layanan Google Play. Misalnya, aplikasi Anda dapat memanggil metode untuk membaca file dari Google Drive, terlepas dari apakah instance GoogleApiClient Anda sudah terhubung atau belum. Setelah koneksi dibuat, permintaan baca yang diantrekan akan dieksekusi. Permintaan tulis akan menghasilkan error jika aplikasi Anda memanggil metode tulis layanan Google Play saat Klien Google API tidak terhubung.

Menggunakan panggilan asinkron

Untuk membuat permintaan asinkron, panggil setResultCallback() di PendingResult dan berikan implementasi antarmuka ResultCallback. Misalnya, berikut permintaan yang dijalankan secara asinkron:

private void loadFile(String filename) {
    // Create a query for a specific filename in Drive.
    Query query = new Query.Builder()
            .addFilter(Filters.eq(SearchableField.TITLE, filename))
            .build();
    // Invoke the query asynchronously with a callback method
    Drive.DriveApi.query(mGoogleApiClient, query)
            .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
        @Override
        public void onResult(DriveApi.MetadataBufferResult result) {
            // Success! Handle the query result.
            // ...
        }
    });
}

Saat aplikasi Anda menerima objek Result dalam callback onResult(), objek tersebut akan dikirim sebagai instance subclass yang sesuai seperti yang ditentukan oleh API yang Anda gunakan, seperti DriveApi.MetadataBufferResult.

Menggunakan panggilan sinkron

Jika Anda ingin kode dieksekusi dalam urutan yang ditentukan secara ketat, mungkin karena hasil dari satu panggilan diperlukan sebagai argumen ke argumen lainnya, Anda dapat membuat permintaan Anda sinkron dengan memanggil await() di PendingResult. Tindakan ini akan memblokir thread dan menampilkan objek Result saat permintaan selesai. Objek ini dikirim sebagai instance subclass yang sesuai, seperti yang ditentukan oleh API yang Anda gunakan, misalnya DriveApi.MetadataBufferResult.

Karena memanggil await() akan memblokir thread hingga hasilnya tiba, aplikasi Anda tidak boleh membuat permintaan sinkron ke Google API pada UI thread. Aplikasi Anda dapat membuat thread baru menggunakan objek AsyncTask, dan menggunakan thread tersebut untuk membuat permintaan sinkron.

Contoh berikut menunjukkan cara membuat permintaan file ke Google Drive sebagai panggilan sinkron:

private void loadFile(String filename) {
    new GetFileTask().execute(filename);
}

private class GetFileTask extends AsyncTask {
    protected void doInBackground(String filename) {
        Query query = new Query.Builder()
                .addFilter(Filters.eq(SearchableField.TITLE, filename))
                .build();
        // Invoke the query synchronously
        DriveApi.MetadataBufferResult result =
                Drive.DriveApi.query(mGoogleApiClient, query).await();

        // Continue doing other stuff synchronously
        // ...
    }
}

Mengakses Wearable API

Wearable API menyediakan saluran komunikasi untuk aplikasi yang berjalan di perangkat genggam dan wearable. API terdiri dari kumpulan objek data yang dapat dikirim dan disinkronkan oleh sistem, dan pemroses yang memberi tahu aplikasi Anda tentang peristiwa penting menggunakan lapisan data. Wearable API tersedia di perangkat yang menjalankan Android 4.3 (API level 18) atau yang lebih baru saat perangkat wearable terhubung dan aplikasi pendamping Wear OS diinstal di perangkat.

Menggunakan Wearable API yang berdiri sendiri

Jika aplikasi Anda menggunakan Wearable API, tetapi bukan Google API lainnya, Anda dapat menambahkan API ini dengan memanggil metode addApi(). Contoh berikut menunjukkan cara menambahkan Wearable API ke instance GoogleApiClient Anda:

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
    .enableAutoManage(this /* FragmentActivity */,
                      this /* OnConnectionFailedListener */)
    .addApi(Wearable.API)
    .build();

Jika Wearable API tidak tersedia, permintaan koneksi yang menyertakan Wearable API akan gagal dengan kode error API_UNAVAILABLE.

Contoh berikut menunjukkan cara menentukan apakah Wearable API tersedia:

// Connection failed listener method for a client that only
// requests access to the Wearable API
@Override
public void onConnectionFailed(ConnectionResult result) {
    if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
        // The Wearable API is unavailable
    }
    // ...
}

Menggunakan Wearable API dengan Google API lainnya

Jika aplikasi Anda menggunakan Wearable API selain Google API lainnya, panggil metode addApiIfAvailable() dan teruskan Wearable API untuk memeriksa apakah metode tersebut tersedia. Anda dapat menggunakan pemeriksaan ini untuk membantu aplikasi menangani kasus saat API tidak tersedia dengan baik.

Contoh berikut menunjukkan cara mengakses Wearable API beserta Drive API:

// Create a GoogleApiClient instance
mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */,
                          this /* OnConnectionFailedListener */)
        .addApi(Drive.API)
        .addApiIfAvailable(Wearable.API)
        .addScope(Drive.SCOPE_FILE)
        .build();

Pada contoh di atas, GoogleApiClient dapat berhasil terhubung dengan Google Drive tanpa terhubung ke Wearable API jika tidak tersedia. Setelah menghubungkan instance GoogleApiClient, pastikan Wearable API tersedia sebelum melakukan panggilan API:

boolean wearAvailable = mGoogleApiClient.hasConnectedApi(Wearable.API);

Mengabaikan Kegagalan Koneksi API

Jika Anda memanggil addApi() dan GoogleApiClient tidak berhasil terhubung ke API tersebut, seluruh operasi koneksi untuk klien tersebut akan gagal dan memicu callback onConnectionFailed().

Anda dapat mendaftarkan kegagalan koneksi API untuk diabaikan menggunakan addApiIfAvailable(). Jika API yang ditambahkan dengan addApiIfAvailable() gagal terhubung karena error yang tidak dapat dipulihkan (seperti API_UNAVAILABLE untuk Wear), API tersebut akan dihapus dari GoogleApiClient Anda dan klien melanjutkan untuk terhubung ke API lain. Namun, jika koneksi API gagal dengan error yang dapat dipulihkan (seperti intent penyelesaian izin OAuth), operasi koneksi klien akan gagal. Saat menggunakan koneksi yang dikelola secara otomatis, GoogleApiClient akan mencoba mengatasi error tersebut jika memungkinkan. Saat menggunakan koneksi yang dikelola secara manual, ConnectionResult yang berisi intent resolusi akan dikirimkan ke callback onConnectionFailed(). Kegagalan koneksi API diabaikan hanya jika tidak ada resolusi untuk kegagalan tersebut dan API ditambahkan dengan addApiIfAvailable(). Untuk mempelajari cara mengimplementasikan penanganan kegagalan koneksi manual, lihat Menangani kegagalan koneksi.

Karena API yang ditambahkan dengan addApiIfAvailable() mungkin tidak selalu ada di instance GoogleApiClient yang terhubung, Anda harus melindungi panggilan ke API ini dengan menambahkan pemeriksaan menggunakan hasConnectedApi(). Untuk mengetahui alasan API tertentu gagal terhubung saat seluruh operasi koneksi berhasil untuk klien, panggil getConnectionResult() dan dapatkan kode error dari objek ConnectionResult. Jika klien memanggil API saat tidak terhubung ke klien, panggilan akan gagal dengan kode status API_NOT_AVAILABLE.

Jika API yang Anda tambahkan melalui addApiIfAvailable() memerlukan satu atau beberapa cakupan, tambahkan cakupan tersebut sebagai parameter dalam panggilan metode addApiIfAvailable(), bukan dengan menggunakan metode addScope(). Cakupan yang ditambahkan menggunakan pendekatan ini mungkin tidak diminta jika koneksi API gagal sebelum mendapatkan izin OAuth, sedangkan cakupan yang ditambahkan dengan addScope() selalu diminta.

Koneksi yang dikelola secara manual

Sebagian besar panduan ini menunjukkan cara menggunakan metode enableAutoManage untuk memulai koneksi yang dikelola secara otomatis dengan error yang diselesaikan secara otomatis. Dalam hampir semua kasus, ini adalah cara terbaik dan termudah untuk terhubung ke Google API dari aplikasi Android Anda. Namun, ada beberapa situasi saat Anda ingin menggunakan koneksi yang dikelola secara manual ke Google API di aplikasi Anda:

  • Untuk mengakses Google API di luar aktivitas atau mempertahankan kontrol koneksi API
  • Untuk menyesuaikan penanganan dan penyelesaian error koneksi

Bagian ini memberikan contoh kasus penggunaan tersebut dan kasus penggunaan lanjutan lainnya.

Memulai koneksi yang dikelola secara manual

Untuk memulai koneksi yang dikelola secara manual ke GoogleApiClient, Anda harus menentukan implementasi untuk antarmuka callback, ConnectionCallbacks dan OnConnectionFailedListener. Antarmuka ini menerima callback sebagai respons terhadap metode connect() asinkron saat koneksi ke layanan Google Play berhasil, gagal, atau ditangguhkan.

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build()

Saat mengelola koneksi secara manual, Anda harus memanggil metode connect() dan disconnect() di titik yang tepat dalam siklus proses aplikasi Anda. Dalam konteks aktivitas, praktik terbaik adalah memanggil connect() dalam metode onStart() aktivitas Anda dan disconnect() dalam metode onStop() aktivitas Anda. Metode connect() dan disconnect() dipanggil secara otomatis saat menggunakan koneksi yang dikelola secara otomatis.

Jika Anda menggunakan GoogleApiClient untuk terhubung ke API yang memerlukan autentikasi, seperti Google Drive atau Google Play Game, ada kemungkinan upaya koneksi pertama Anda akan gagal dan aplikasi Anda akan menerima panggilan ke onConnectionFailed() dengan error SIGN_IN_REQUIRED karena akun pengguna tidak ditentukan.

Menangani kegagalan koneksi

Saat aplikasi Anda menerima panggilan ke callback onConnectionFailed(), Anda harus memanggil hasResolution() pada objek ConnectionResult yang diberikan. Jika menampilkan nilai benar, aplikasi Anda dapat meminta pengguna segera mengambil tindakan untuk mengatasi error dengan memanggil startResolutionForResult() pada objek ConnectionResult. Metode startResolutionForResult() berperilaku sama seperti startActivityForResult() dalam situasi ini, dan meluncurkan aktivitas yang sesuai dengan konteks yang membantu pengguna menyelesaikan error (seperti aktivitas yang membantu pengguna memilih akun).

Jika hasResolution() menampilkan salah, aplikasi Anda harus memanggil GoogleApiAvailability.getErrorDialog(), yang meneruskan kode error ke metode ini. Tindakan ini akan menampilkan Dialog yang disediakan oleh layanan Google Play yang sesuai dengan error. Dialog ini dapat cukup menyediakan pesan yang menjelaskan error tersebut, atau juga dapat memberikan tindakan untuk meluncurkan aktivitas yang dapat mengatasi error (seperti saat pengguna perlu menginstal versi layanan Google Play yang lebih baru).

Misalnya, metode callback onConnectionFailed() sekarang akan terlihat seperti ini:

public class MyActivity extends Activity
        implements ConnectionCallbacks, OnConnectionFailedListener {

    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 1001;
    // Unique tag for the error dialog fragment
    private static final String DIALOG_ERROR = "dialog_error";
    // Bool to track whether the app is already resolving an error
    private boolean mResolvingError = false;

    // ...

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
            } catch (SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GoogleApiAvailability.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
        }
    }

    // The rest of this code is all about building the error dialog

    /* Creates a dialog for an error message */
    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getSupportFragmentManager(), "errordialog");
    }

    /* Called from ErrorDialogFragment when the dialog is dismissed. */
    public void onDialogDismissed() {
        mResolvingError = false;
    }

    /* A fragment to display an error dialog */
    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() { }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
            return GoogleApiAvailability.getInstance().getErrorDialog(
                    this.getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            ((MyActivity) getActivity()).onDialogDismissed();
        }
    }
}

Setelah pengguna menyelesaikan dialog yang disediakan oleh startResolutionForResult() atau menutup pesan yang disediakan oleh GoogleApiAvailability.getErrorDialog(), aktivitas Anda akan menerima callback onActivityResult() dengan kode hasil RESULT_OK. Aplikasi Anda kemudian dapat memanggil connect() lagi. Contoh:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_RESOLVE_ERROR) {
        mResolvingError = false;
        if (resultCode == RESULT_OK) {
            // Make sure the app is not already connected or attempting to connect
            if (!mGoogleApiClient.isConnecting() &&
                    !mGoogleApiClient.isConnected()) {
                mGoogleApiClient.connect();
            }
        }
    }
}

Dalam kode di atas, Anda mungkin melihat boolean, mResolvingError. Hal ini membantu melacak status aplikasi saat pengguna menyelesaikan error untuk menghindari upaya berulang untuk menyelesaikan error yang sama. Misalnya, saat dialog pemilih akun ditampilkan untuk membantu pengguna mengatasi error SIGN_IN_REQUIRED, pengguna dapat memutar layar. Tindakan ini akan membuat ulang aktivitas Anda dan menyebabkan metode onStart() dipanggil kembali, yang kemudian memanggil connect() lagi. Tindakan ini akan menghasilkan panggilan lain ke startResolutionForResult(), yang membuat dialog pemilih akun lain di depan dialog yang sudah ada.

Boolean ini hanya memenuhi tujuan yang diinginkan jika tetap ada di seluruh instance aktivitas. Bagian berikutnya menjelaskan cara mempertahankan status penanganan error aplikasi Anda, terlepas dari tindakan atau peristiwa pengguna lain yang terjadi di perangkat.

Mempertahankan status saat menyelesaikan error

Agar tidak mengeksekusi kode di onConnectionFailed() saat upaya sebelumnya untuk mengatasi error sedang berlangsung, Anda harus mempertahankan boolean yang melacak apakah aplikasi sudah mencoba menyelesaikan error.

Seperti yang ditunjukkan dalam contoh kode di atas, aplikasi Anda harus menetapkan boolean ke true setiap kali memanggil startResolutionForResult() atau menampilkan dialog dari GoogleApiAvailability.getErrorDialog(). Kemudian, saat aplikasi Anda menerima RESULT_OK dalam callback onActivityResult(), setel boolean ke false.

Untuk terus melacak boolean meskipun aktivitas dimulai ulang (seperti saat pengguna memutar layar), simpan boolean dalam data instance tersimpan aktivitas menggunakan onSaveInstanceState():

private static final String STATE_RESOLVING_ERROR = "resolving_error";

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
}

Kemudian, pulihkan status tersimpan selama onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ...
    mResolvingError = savedInstanceState != null
            && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
}

Sekarang Anda siap menjalankan aplikasi dengan aman dan terhubung ke layanan Google Play secara manual.