Java tutorial
/******************************************************************************* * Copyright 2011-2013 Sergey Tarasevich * * 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.nostra13.universalimageloader.sample.ui.activity; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; import android.os.*; import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat; import android.view.View; import android.util.Log; import android.widget.Toast; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.plus.Plus; import com.google.android.gms.plus.model.people.Person; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.sample.Constants; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.utils.L; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class HomeActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener { private static final String TEST_FILE_NAME = "Universal Image Loader @#&=+-_.,!()~'%20.png"; private static final String TAG = "HomeActivity"; /* Request code used to invoke sign in user interactions. */ private static final int RC_SIGN_IN = 0; // /* Client used to interact with Google APIs. */ // private GoogleApiClient mGoogleApiClient; /* Is there a ConnectionResult resolution in progress? */ private boolean mIsResolving = false; /* Should we automatically resolve ConnectionResults when possible? */ private boolean mShouldResolve = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_home); getActionBar().hide(); findViewById(R.id.btn_gplus_login).setOnClickListener(this); File testImageOnSdCard = new File("/mnt/sdcard", TEST_FILE_NAME); if (!testImageOnSdCard.exists()) { copyTestImageToSdCard(testImageOnSdCard); } // Build GoogleApiClient with access to basic profile Constants.mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this) .addOnConnectionFailedListener(this).addApi(Plus.API) // .addScope(new Scope(Scopes.PROFILE)) .addScope(Plus.SCOPE_PLUS_PROFILE).addScope(Plus.SCOPE_PLUS_LOGIN).build(); } @Override public void onConnectionSuspended(int i) { // The connection to Google Play services was lost. The GoogleApiClient will automatically // attempt to re-connect. Any UI elements that depend on connection to Google APIs should // be hidden or disabled until onConnected is called again. Log.w(TAG, "onConnectionSuspended:" + i); } @Override public void onConnectionFailed(ConnectionResult connectionResult) { // Could not connect to Google Play Services. The user needs to select an account, // grant permissions or resolve an error in order to sign in. Refer to the javadoc for // ConnectionResult to see possible error codes. Log.d(TAG, "onConnectionFailed:" + connectionResult); if (!mIsResolving && mShouldResolve) { if (connectionResult.hasResolution()) { try { connectionResult.startResolutionForResult(this, RC_SIGN_IN); mIsResolving = true; } catch (IntentSender.SendIntentException e) { Log.e(TAG, "Could not resolve ConnectionResult.", e); mIsResolving = false; Constants.mGoogleApiClient.connect(); } } else { // Could not resolve the connection result, show the user an // error dialog. showErrorDialog(connectionResult); } } else { // Show the signed-out UI //showSignedOutUI(); Toast.makeText(getApplicationContext(), "Signed out...", Toast.LENGTH_LONG).show(); } } @Override protected void onStart() { super.onStart(); } @Override protected void onStop() { Constants.mGoogleApiClient.disconnect(); super.onStop(); } private void showErrorDialog(ConnectionResult connectionResult) { GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance(); int resultCode = apiAvailability.isGooglePlayServicesAvailable(this); if (resultCode != ConnectionResult.SUCCESS) { if (apiAvailability.isUserResolvableError(resultCode)) { apiAvailability .getErrorDialog(this, resultCode, RC_SIGN_IN, new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { mShouldResolve = false; showSignedOutUI(); } }).show(); } else { Log.w(TAG, "Google Play Services Error:" + connectionResult); String errorString = apiAvailability.getErrorString(resultCode); Toast.makeText(this, errorString, Toast.LENGTH_SHORT).show(); mShouldResolve = false; showSignedOutUI(); } } } private void showSignedInUI() { updateUI(true); } private void showSignedOutUI() { updateUI(false); } private void updateUI(boolean isSignedIn) { if (isSignedIn) { Person currentPerson = Plus.PeopleApi.getCurrentPerson(Constants.mGoogleApiClient); if (currentPerson != null) { // Show signed-in user's name String name = currentPerson.getDisplayName(); // mStatus.setText(getString(R.string.signed_in_fmt, name)); // Show users' email address (which requires GET_ACCOUNTS permission) if (checkAccountsPermission()) { String currentAccount = Plus.AccountApi.getAccountName(Constants.mGoogleApiClient); //((TextView) findViewById(R.id.email)).setText(currentAccount); } } else { // If getCurrentPerson returns null there is generally some error with the // configuration of the application (invalid Client ID, Plus API not enabled, etc). //Log.w(TAG, getString(R.string.error_null_person)); // mStatus.setText(getString(R.string.signed_in_err)); Log.w(TAG, "Null person"); } // Set button visibility // findViewById(R.id.sign_in_button).setVisibility(View.GONE); // findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE); } else { // Show signed-out message and clear email field // mStatus.setText(R.string.signed_out); // ((TextView) findViewById(R.id.email)).setText(""); Log.w(TAG, "Signed out"); // Set button visibility // findViewById(R.id.sign_in_button).setEnabled(true); // findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE); // findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE); } } /** * Check if we have the GET_ACCOUNTS permission and request it if we do not. * @return true if we have the permission, false if we do not. */ private boolean checkAccountsPermission() { final String perm = Manifest.permission.GET_ACCOUNTS; int permissionCheck = ContextCompat.checkSelfPermission(this, perm); // if (permissionCheck == PackageManager.PERMISSION_GRANTED) { // // We have the permission // return true; // } else if (ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) { // // Need to show permission rationale, display a snackbar and then request // // the permission again when the snackbar is dismissed. // Snackbar.make(findViewById(R.id.main_layout), // R.string.contacts_permission_rationale, // Snackbar.LENGTH_INDEFINITE) // .setAction(android.R.string.ok, new View.OnClickListener() { // @Override // public void onClick(View v) { // // Request the permission again. // ActivityCompat.requestPermissions(MainActivity.this, // new String[]{perm}, // RC_PERM_GET_ACCOUNTS); // } // }).show(); // return false; // } else { // // No explanation needed, we can request the permission. // ActivityCompat.requestPermissions(this, // new String[]{perm}, // RC_PERM_GET_ACCOUNTS); // return false; // } return false; } /** * Determine whether <em>you</em> have been granted a particular permission. * * @param permission The name of the permission being checked. * * @return {@link android.content.pm.PackageManager#PERMISSION_GRANTED} if you have the * permission, or {@link android.content.pm.PackageManager#PERMISSION_DENIED} if not. * * @see android.content.pm.PackageManager#checkPermission(String, String) */ public static int checkSelfPermission(@NonNull Context context, @NonNull String permission) { if (permission == null) { throw new IllegalArgumentException("permission is null"); } return context.checkPermission(permission, android.os.Process.myPid(), android.os.Process.myUid()); } /** * Returns the absolute path to the directory on the filesystem similar to * {@link Context#getFilesDir()}. The difference is that files placed under this * directory will be excluded from automatic backup to remote storage on * devices running {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later. See * {@link android.app.backup.BackupAgent BackupAgent} for a full discussion * of the automatic backup mechanism in Android. * * <p>No permissions are required to read or write to the returned path, since this * path is internal storage. * * @return The path of the directory holding application files that will not be * automatically backed up to remote storage. * * @see android.content.Context.getFilesDir */ // public final File getNoBackupFilesDir(Context context) { // final int version = Build.VERSION.SDK_INT; // if (version >= 21) { // return ContextCompatApi21.getNoBackupFilesDir(context); // } else { // ApplicationInfo appInfo = context.getApplicationInfo(); // return createFilesDir(new File(appInfo.dataDir, "no_backup")); // } // } /** * Returns the absolute path to the application specific cache directory on * the filesystem designed for storing cached code. On devices running * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or later, the system will delete * any files stored in this location both when your specific application is * upgraded, and when the entire platform is upgraded. * <p> * This location is optimal for storing compiled or optimized code generated * by your application at runtime. * <p> * Apps require no extra permissions to read or write to the returned path, * since this path lives in their private storage. * * @return The path of the directory holding application code cache files. */ // public final File getCodeCacheDir(Context context) { // final int version = Build.VERSION.SDK_INT; // if (version >= 21) { // return ContextCompatApi21.getCodeCacheDir(context); // } else { // ApplicationInfo appInfo = context.getApplicationInfo(); // return createFilesDir(new File(appInfo.dataDir, "code_cache")); // } // } @Override public void onBackPressed() { ImageLoader.getInstance().stop(); super.onBackPressed(); } @Override public void onClick(View v) { if (v.getId() == R.id.btn_gplus_login) { onSignInClicked(); } // ... } private void onSignInClicked() { // User clicked the sign-in button, so begin the sign-in process and automatically // attempt to resolve any errors that occur. mShouldResolve = true; Constants.mGoogleApiClient.connect(); // Show a message to the user that we are signing in. //mStatusTextView.setText(R.string.signing_in); Toast.makeText(getApplicationContext(), "Signing In...", Toast.LENGTH_LONG).show(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data); if (requestCode == RC_SIGN_IN) { // If the error resolution was not successful we should not resolve further. if (resultCode != RESULT_OK) { mShouldResolve = false; } mIsResolving = false; Constants.mGoogleApiClient.connect(); } } @Override public void onConnected(Bundle bundle) { // onConnected indicates that an account was selected on the device, that the selected // account has granted any requested permissions to our app and that we were able to // establish a service connection to Google Play services. Log.d(TAG, "onConnected:" + bundle); mShouldResolve = false; // Show the signed-in UI showSignedInUI(); Toast.makeText(getApplicationContext(), "Signed In...", Toast.LENGTH_LONG).show(); if (Plus.PeopleApi.getCurrentPerson(Constants.mGoogleApiClient) != null) { Person currentPerson = Plus.PeopleApi.getCurrentPerson(Constants.mGoogleApiClient); String personName = currentPerson.getDisplayName(); String personPhoto = currentPerson.getImage().getUrl(); String personGooglePlusProfile = currentPerson.getUrl(); Toast.makeText(getApplicationContext(), "User Info..." + personName + " " + personGooglePlusProfile + " " + personGooglePlusProfile, Toast.LENGTH_LONG).show(); Log.v(TAG, "UserInfo:" + personName + " " + personGooglePlusProfile + " " + personGooglePlusProfile); } Intent intent = new Intent(this, ProductListActivity.class); intent.putExtra(Constants.Extra.FRAGMENT_INDEX, 0); startActivity(intent); } private void copyTestImageToSdCard(final File testImageOnSdCard) { new Thread(new Runnable() { @Override public void run() { try { InputStream is = getAssets().open(TEST_FILE_NAME); FileOutputStream fos = new FileOutputStream(testImageOnSdCard); byte[] buffer = new byte[8192]; int read; try { while ((read = is.read(buffer)) != -1) { fos.write(buffer, 0, read); } } finally { fos.flush(); fos.close(); is.close(); } } catch (IOException e) { L.w("Can't copy test image onto SD card"); } } }).start(); } }