Java tutorial
/* * Copyright (C) 2015 Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.android.apps.santatracker.games.common; import android.annotation.SuppressLint; import android.content.Intent; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Bundle; import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.Window; import com.google.android.apps.santatracker.R; import com.google.android.apps.santatracker.games.PlayGamesFragment; import com.google.android.apps.santatracker.games.SignInListener; import com.google.android.apps.santatracker.games.gumball.Utils; import com.google.android.apps.santatracker.util.ImmersiveModeHelper; import com.google.android.apps.santatracker.util.SantaLog; import com.google.android.gms.appindexing.AppIndex; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.common.api.Status; @SuppressLint("Registered") public abstract class GameActivity extends AppCompatActivity implements SignInListener { private static final String TAG = "GameActivity"; /** Non-visible fragment encapsulating Play Games logic. **/ private PlayGamesFragment mGamesFragment; // we need a separate API client for App Indexing // so that view and ViewEnd events can be recorded even // when the user is not signed in GoogleApiClient mApiClient = null; boolean mSignedIn = false; // base URL for deep links required by App Indexing // Deep link intent filter entries in AndroidManifest.xml must match // the data part of this prefix private static Uri BASE_APP_URI; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); supportRequestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayShowTitleEnabled(false); actionBar.setHomeButtonEnabled(false); actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setBackgroundDrawable( new ColorDrawable(ContextCompat.getColor(this, android.R.color.transparent))); } mGamesFragment = PlayGamesFragment.getInstance(this, this); mApiClient = new GoogleApiClient.Builder(this).addApi(AppIndex.APP_INDEX_API).build(); // add App Indexing API BASE_APP_URI = Uri.parse("android-app://" + getApplicationContext().getPackageName() + "/" + getResources().getString(R.string.santa_tracker_deep_link_prefix)); if (Utils.hasKitKat()) { ImmersiveModeHelper.setImmersiveSticky(getWindow()); ImmersiveModeHelper.installSystemUiVisibilityChangeListener(getWindow()); } } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (Utils.hasKitKat() && hasFocus) { ImmersiveModeHelper.setImmersiveSticky(getWindow()); } } @Override public void onStart() { super.onStart(); appIndexingRecordView(); } @Override public void onStop() { super.onStop(); appIndexingRecordViewEnd(); } @Override public void onActivityResult(int req, int resp, Intent data) { super.onActivityResult(req, resp, data); mGamesFragment.onActivityResult(req, resp, data); } @Override public void onSignInFailed() { mSignedIn = false; } @Override public void onSignInSucceeded() { mSignedIn = true; } public boolean isSignedIn() { return mSignedIn; } public void beginUserInitiatedSignIn() { mGamesFragment.beginUserInitiatedSignIn(); } public GoogleApiClient getGamesApiClient() { return mGamesFragment.getGamesApiClient(); } /** * Connect the client, record the view using App Indexing API. * We're not connecting the client in the activity lifecycle method * to maintain symmetry with appIndexingRecordViewEnd which * disconnects the client once the view is recorded */ private void appIndexingRecordView() { // connect the client mApiClient.connect(); // Define a title for your current page, shown in autocompletion UI final String title = getGameTitle(); final Uri appUri = getGameDeepLinkUri(); // Call the App Indexing API view method PendingResult<Status> result = AppIndex.AppIndexApi.view(mApiClient, this, appUri, title, null, null); result.setResultCallback(new ResultCallback<Status>() { @Override public void onResult(Status status) { if (status.isSuccess()) { SantaLog.v(TAG, String.format("App Indexing API: Recorded [" + title + "] view successfully.")); } else { Log.e(TAG, "App Indexing API: There was an error recording the view." + status.toString()); } } }); } /** * Record the view end using the App Indexing API, * disconnect the client once the view is recorded. */ private void appIndexingRecordViewEnd() { final Uri appUri = getGameDeepLinkUri(); final String title = getGameTitle(); PendingResult<Status> result = AppIndex.AppIndexApi.viewEnd(mApiClient, this, appUri); result.setResultCallback(new ResultCallback<Status>() { @Override public void onResult(Status status) { mApiClient.disconnect(); // disconnecting here because of a potential race if (status.isSuccess()) { Log.v(TAG, "App Indexing API: Recorded [" + title + "] view end successfully."); } else { Log.e(TAG, "App Indexing API: There was an error recording the view end." + status.toString()); } } }); } /** * See https://developers.google.com/app-indexing/webmasters/appindexingapi * @return deep link representing this game */ public Uri getGameDeepLinkUri() { return BASE_APP_URI.buildUpon().appendPath(String.valueOf(getGameId())).build(); } /** * This is the ID which becomes a part of the deep link. * For example: * android-app://com.google.android.apps.santatracker/http/google.com/santatracker/gumball * This value need not be human-readable, it sent in the Intent back to the * Santa Tracker by the Google App. * When extending this class and providing new deep links, make sure * to update the corresponding intent-filter in AndroidManifest.xml. * @return deep link component to identify the game to app indexing API */ public abstract String getGameId(); /** * This name will be shown to users in the Google app for autocompletion * @return user-visible game title */ public abstract String getGameTitle(); }