Google Plus Integration with Android App - java

With help from the google documentation, I'm trying to implement a 'Google Sign In' integration. I have done everything from creating the developer console project, pasted in the SHA1 code, and downloaded the google-services.json and put this into my project.
When i click on the sign in button, the screen flashes quickly and then nothing really happens.
Viewing the logcat, all it says is
05-02 20:15:58.433 18625-18625/com.listcoapps.ukeen D/SignInActivity: handleSignInResult:false
05-02 20:15:58.434 18625-18625/com.listcoapps.ukeen I/System.out: Status{statusCode=INTERNAL_ERROR, resolution=null}
My code is solely based off the google developer documentation.
SignInActivity.Java
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
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.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
/**
* Activity to demonstrate basic retrieval of the Google user's ID, email address, and basic
* profile.
*/
public class SignInActivity extends AppCompatActivity implements
GoogleApiClient.OnConnectionFailedListener,
View.OnClickListener {
private static final String TAG = "SignInActivity";
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private TextView mStatusTextView;
private ProgressDialog mProgressDialog;
private boolean mIntentInProgress;
private ConnectionResult mConnectionResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
// [START customize_button]
// Customize sign-in button. The sign-in button can be displayed in
// multiple sizes and color schemes. It can also be contextually
// rendered based on the requested scopes. For example. a red button may
// be displayed when Google+ scopes are requested, but a white button
// may be displayed when only basic profile is requested. Try adding the
// Scopes.PLUS_LOGIN scope to the GoogleSignInOptions to see the
// difference.
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
// [END customize_button]
}
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
updateUI(true);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
System.out.println(result.getStatus());
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END signOut]
// [START revokeAccess]
private void revokeAccess() {
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END revokeAccess]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
Log.d(TAG, "onConnectionFailed:" + connectionResult);
}
private void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(getString(R.string.loading));
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
} else {
mStatusTextView.setText(R.string.signed_out);
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE);
}
}
private void resolveSignInError() {
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
//startIntentSenderForResult(mConnectionResult.getIntentSender(),RC_SIGN_IN, null, 0, 0, 0);
mConnectionResult.startResolutionForResult(this,RC_SIGN_IN);
} catch (IntentSender.SendIntentException e) {
// The intent was canceled before it was sent. Return to the default
// state and attempt to connect to get an updated ConnectionResult.
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
signIn();
break;
case R.id.sign_out_button:
signOut();
break;
case R.id.disconnect_button:
revokeAccess();
break;
}
}
}
I really can't work out why this isn't working and some expert knowledge would really help!
Thank you.

By integrating google plus login in your apps, you can get all the user details in one shot. Not only login, you can do other things like posting to their g+ account, getting list of circles, friends list and lot more. The major advantage of integrating G+ login is, you can drive more users to your app by providing quicker & easiest way of registration process.
Try this tutorial you will get idea and easily integrate google plus to your project
Google Plus and Login Integration to android App
Or
Try from developer site

Related

onActivityResult always returning not authorized

I'm trying to just sign a user to the app to be able to use Google Drive API, but in my activityResults I always get the else statement and that means the user is not authorized or the sign in have failed. Why might this be? I have followed the official docs.
Here is my code:
private static final int REQUEST_CODE_SIGN_IN = 0;
private DriveClient mDriveClient;
private DriveResourceClient mDriveResourceClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
signIn();
}
private void initializeDriveClient(GoogleSignInAccount signInAccount) {
mDriveClient = Drive.getDriveClient(getApplicationContext(), signInAccount);
mDriveResourceClient = Drive.getDriveResourceClient(getApplicationContext(), signInAccount);
}
/**
* Starts the sign-in process and initializes the Drive client.
*/
private void signIn() {
Set<Scope> requiredScopes = new HashSet<>(2);
requiredScopes.add(Drive.SCOPE_FILE);
requiredScopes.add(Drive.SCOPE_APPFOLDER);
GoogleSignInAccount signInAccount = GoogleSignIn.getLastSignedInAccount(this);
if (signInAccount != null && signInAccount.getGrantedScopes().containsAll(requiredScopes)) {
initializeDriveClient(signInAccount);
} else {
GoogleSignInOptions signInOptions =
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(Drive.SCOPE_FILE)
.requestScopes(Drive.SCOPE_APPFOLDER)
.build();
GoogleSignInClient googleSignInClient = GoogleSignIn.getClient(this, signInOptions);
startActivityForResult(googleSignInClient.getSignInIntent(), REQUEST_CODE_SIGN_IN);
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
if (resultCode == Activity.RESULT_OK) {
// App is authorized, you can go back to sending the API request
Log.e("SignIn", "App autorizada");
} else {
// User denied access, show him the account chooser again
Log.e("SignIn", "App No Autorizada");
finish();
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
Solved my own problem pasting the SHA1 and package name into credentials in my google console, it seemed i was doing something wrong with the credentials.
Code looks fine. Check if you have added google_services.json file in the project. Also check if th SHA1 key is correct.

App Crashes On Clicking To Start Location Update

I am developing an app that uses fingerprint authentication to send the location of user over certain duration ex 30 mins in form of intervals of 10 mins. i have used certain code to develop the app. But app crashes on clicking start update button.
Note : Summary of app crash says java.lang.SecurityException: Client must have ACCESS_Fine_LOCATION permission to request PRIORITY_HIGH_ACCURACY locations.
Following is the code
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.gms.location.sample.locationupdates">
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.location.gps" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".FingerprintActivity"
android:label="Fingerprint">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
</activity>
</application>
</manifest>
FingerprintActivity.java
import android.Manifest;
import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
public class FingerprintActivity extends AppCompatActivity {
private KeyStore keyStore;
// Variable used for storing the key in the Android Keystore container
private static final String KEY_NAME = "androidHive";
private Cipher cipher;
private TextView textView;
public void sendMessage(View view)
{
Intent intent = new Intent(FingerprintActivity.this, MainActivity.class);
startActivity(intent);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fingerprint);
// Initializing both Android Keyguard Manager and Fingerprint Manager
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
textView = (TextView) findViewById(R.id.errorText);
// Check whether the device has a Fingerprint sensor.
if(!fingerprintManager.isHardwareDetected()){
/**
* An error message will be displayed if the device does not contain the fingerprint hardware.
* However if you plan to implement a default authentication method,
* you can redirect the user to a default authentication activity from here.
* Example:
* Intent intent = new Intent(this, DefaultAuthenticationActivity.class);
* startActivity(intent);
*/
textView.setText("Your Device does not have a Fingerprint Sensor");
}else {
// Checks whether fingerprint permission is set on manifest
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
textView.setText("Fingerprint authentication permission not enabled");
}else{
// Check whether at least one fingerprint is registered
if (!fingerprintManager.hasEnrolledFingerprints()) {
textView.setText("Register at least one fingerprint in Settings");
}else{
// Checks whether lock screen security is enabled or not
if (!keyguardManager.isKeyguardSecure()) {
textView.setText("Lock screen security not enabled in Settings");
}else{
generateKey();
if (cipherInit()) {
FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher);
FingerprintHandler helper = new FingerprintHandler(this);
helper.startAuth(fingerprintManager, cryptoObject);
}
}
}
}
}
}
#TargetApi(Build.VERSION_CODES.M)
protected void generateKey() {
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (Exception e) {
e.printStackTrace();
}
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
throw new RuntimeException("Failed to get KeyGenerator instance", e);
}
try {
keyStore.load(null);
keyGenerator.init(new
KeyGenParameterSpec.Builder(KEY_NAME,
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setUserAuthenticationRequired(true)
.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_PKCS7)
.build());
keyGenerator.generateKey();
} catch (NoSuchAlgorithmException |
InvalidAlgorithmParameterException
| CertificateException | IOException e) {
throw new RuntimeException(e);
}
}
#TargetApi(Build.VERSION_CODES.M)
public boolean cipherInit() {
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException("Failed to get Cipher", e);
}
try {
keyStore.load(null);
SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME,
null);
cipher.init(Cipher.ENCRYPT_MODE, key);
return true;
} catch (KeyPermanentlyInvalidatedException e) {
return false;
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) {
throw new RuntimeException("Failed to init Cipher", e);
}
}
}
FingerprintHandler
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.CancellationSignal;
import android.support.v4.app.ActivityCompat;
import android.widget.TextView;
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private Context context;
// Constructor
public FingerprintHandler(Context mContext) {
context = mContext;
}
public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) {
CancellationSignal cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
#Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
this.update("Fingerprint Authentication error\n" + errString);
}
#Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
this.update("Fingerprint Authentication help\n" + helpString);
}
#Override
public void onAuthenticationFailed() {
this.update("Fingerprint Authentication failed.");
}
#Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
((Activity) context).finish();
Intent intent = new Intent(context, MainActivity.class);
context.startActivity(intent);
}
private void update(String e){
TextView textView = (TextView) ((Activity)context).findViewById(R.id.errorText);
textView.setText(e);
}
}
MainActivity
import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import java.text.DateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity implements
ConnectionCallbacks,
OnConnectionFailedListener,
LocationListener {
protected static final String TAG = "MainActivity";
/**
* Constant used in the location settings dialog.
*/
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
// Keys for storing activity state in the Bundle.
protected final static String KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected final static String KEY_LOCATION = "location";
protected final static String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest mLocationRequest;
protected LocationSettingsRequest mLocationSettingsRequest;
protected Location mCurrentLocation;
// UI Widgets.
protected Button mStartUpdatesButton;
protected Button mStopUpdatesButton;
protected TextView mLastUpdateTimeTextView;
protected TextView mLatitudeTextView;
protected TextView mLongitudeTextView;
protected TextView mLocationInadequateWarning;
// Labels.
protected String mLatitudeLabel;
protected String mLongitudeLabel;
protected String mLastUpdateTimeLabel;
protected Boolean mRequestingLocationUpdates;
protected String mLastUpdateTime;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Locate the UI widgets.
mStartUpdatesButton = (Button) findViewById(R.id.start_updates_button);
mStopUpdatesButton = (Button) findViewById(R.id.stop_updates_button);
mLatitudeTextView = (TextView) findViewById(R.id.latitude_text);
mLongitudeTextView = (TextView) findViewById(R.id.longitude_text);
mLastUpdateTimeTextView = (TextView) findViewById(R.id.last_update_time_text);
mLocationInadequateWarning = (TextView) findViewById(R.id.location_inadequate_warning);
// Set labels.
mLatitudeLabel = getResources().getString(R.string.latitude_label);
mLongitudeLabel = getResources().getString(R.string.longitude_label);
mLastUpdateTimeLabel = getResources().getString(R.string.last_update_time_label);
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
// Update values using data stored in the Bundle.
updateValuesFromBundle(savedInstanceState);
// Kick off the process of building the GoogleApiClient, LocationRequest, and
// LocationSettingsRequest objects.
buildGoogleApiClient();
createLocationRequest();
buildLocationSettingsRequest();
}
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateUI();
}
}
/**
* Builds a GoogleApiClient. Uses the {#code #addApi} method to request the
* LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
// Sets the desired interval for active location updates. This interval is
// inexact. You may not receive updates at all if no location sources are available, or
// you may receive them slower than requested. You may also receive updates faster than
// requested if other applications are requesting location at a faster interval.
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates faster than this value.
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
/**
* Uses a {#link com.google.android.gms.location.LocationSettingsRequest.Builder} to build
* a {#link com.google.android.gms.location.LocationSettingsRequest} that is used for checking
* if a device has the needed location settings.
*/
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
/**
* The callback invoked when
* {#link com.google.android.gms.location.SettingsApi#checkLocationSettings(GoogleApiClient,
* LocationSettingsRequest)} is called. Examines the
* {#link com.google.android.gms.location.LocationSettingsResult} object and determines if
* location settings are adequate. If they are not, begins the process of presenting a location
* settings dialog to the user.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
// Nothing to do. startLocationupdates() gets called in onResume again.
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
mRequestingLocationUpdates = false;
updateUI();
break;
}
break;
}
}
/**
* Handles the Start Updates button and requests start of location updates. Does nothing if
* updates have already been requested.
*/
public void startUpdatesButtonHandler(View view) {
if (!mRequestingLocationUpdates) {
mRequestingLocationUpdates = true;
setButtonsEnabledState();
startLocationUpdates();
}
}
/**
* Handles the Stop Updates button, and requests removal of location updates.
*/
public void stopUpdatesButtonHandler(View view) {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
stopLocationUpdates();
}
/**
* Requests location updates from the FusedLocationApi.
*/
protected void startLocationUpdates() {
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
).setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, MainActivity.this);
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Attempting to upgrade " +
"location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Log.e(TAG, errorMessage);
Toast.makeText(MainActivity.this, errorMessage, Toast.LENGTH_LONG).show();
mRequestingLocationUpdates = false;
}
updateUI();
}
});
}
/**
* Updates all UI fields.
*/
private void updateUI() {
setButtonsEnabledState();
updateLocationUI();
}
/**
* Disables both buttons when functionality is disabled due to insuffucient location settings.
* Otherwise ensures that only one button is enabled at any time. The Start Updates button is
* enabled if the user is not requesting location updates. The Stop Updates button is enabled
* if the user is requesting location updates.
*/
private void setButtonsEnabledState() {
if (mRequestingLocationUpdates) {
mStartUpdatesButton.setEnabled(false);
mStopUpdatesButton.setEnabled(true);
} else {
mStartUpdatesButton.setEnabled(true);
mStopUpdatesButton.setEnabled(false);
}
}
/**
* Sets the value of the UI fields for the location latitude, longitude and last update time.
*/
private void updateLocationUI() {
if (mCurrentLocation != null) {
mLatitudeTextView.setText(String.format("%s: %f", mLatitudeLabel,
mCurrentLocation.getLatitude()));
mLongitudeTextView.setText(String.format("%s: %f", mLongitudeLabel,
mCurrentLocation.getLongitude()));
mLastUpdateTimeTextView.setText(String.format("%s: %s", mLastUpdateTimeLabel,
mLastUpdateTime));
}
}
/**
* Removes location updates from the FusedLocationApi.
*/
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
mRequestingLocationUpdates = false;
setButtonsEnabledState();
}
});
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onResume() {
super.onResume();
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
updateUI();
}
#Override
protected void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
if (mRequestingLocationUpdates) {
Log.i(TAG, "in onConnected(), starting location updates");
startLocationUpdates();
}
}
/**
* Callback that fires when the location changes.
*/
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
#Override
public void onConnectionSuspended(int cause) {
Log.i(TAG, "Connection suspended");
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
/**
* Stores activity data in the Bundle.
*/
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates);
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
minSdkVersion 23 targetSdkVersion 24
Targeting SDK 23+ require you support Runtime Permissions. Your manifest is <uses-permission>s are irrelevant in such case (and can be removed if you not targetting lower SDKs). As you have no support for Runtime Permissions your app is not granted GPS access hence the crash with SecurityException.
Docs: https://developer.android.com/training/permissions/requesting.html
Quick solution: if you can, lower targetSdk (and minSdk) below 23. If you for any reason cannot, you must have Runtime Permissions implemented. There are some libs helping with the task - just google for it.

GoogleAPIClient is null even when logged in successfully

I have successfully added Google authentication in android app. I am able to login properly without any error. But when i try to logout GoogleApiClient is giving me null so that i am failing to logout successfully. I tried so many answers here but nothing worked for me. Below is the code I entered in my MainActivity.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if(ApplicationPreferences.get().isFirstTimeUser()) {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(GmailScopes.GMAIL_READONLY))
.requestServerAuthCode(Constants.SERVER_CLIENT_ID, true)
.requestEmail()
.build();
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
signInButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.sign_in_button:
signIn();
break;
}
}
});
signInButton.setVisibility(View.VISIBLE);
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(MainActivity.this)
.enableAutoManage(MainActivity.this, MainActivity.this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(MainActivity.this)
.build();
mGoogleApiClient.connect();
} else {
loadMainActivity();
}
}
}, 2000);
Below is my signOut method as specified by Documentation but i failed to understand their statement You must confirm that GoogleApiClient.onConnected has been called before you call signOut. Need some idea what I am doing wrong here.
if (mGoogleApiClient != null)
{
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
ApplicationPreferences.get().clearAll();
Intent intent = getIntent();
finish();
startActivity(intent);
}
});
}
My OnStart()
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
The error, if you say callbacks are not being called, might just be the sign that you may not have connected first. I imagine you have implemented the callbacks and they are not being called?
In any case, to "handle" the error situation, you may want to check if the GoogleApiClient is connected.. like this:
if (mGoogleApiClient != null && mGoogleApiClient.isConnected())
{
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
ApplicationPreferences.get().clearAll();
Intent intent = getIntent();
finish();
startActivity(intent);
}
});
}
else{
Log.w("SomeTag", "It looks like GoogleApiClient is not connected");
}
But I do think you need to check if there are any errors (for instance does onConnectionFailed(ConnectionResult result) get called instead? What error do you see?
Hope this helps.

Application crashed if use leaderboard

I have a problem with leadherBoard via Google Games.
I have login into app. login run good.
I have copied some block of code from internet and login run good...
But If I want send score in LatherBoard or work with latherboard.
Games.Leaderboards.submitScore(mGoogleApiClient, getString(LEADERBOARD_ID)), 137);
startActivityForResult(Games.Leaderboards.getLeaderboardIntent(mGoogleApiClient,
getString(LEADERBOARD_ID)), REQUEST_LEADERBOARD);
Becoause I testing app I have thise code under Button. But If I press this button Application crashed.
But I don't know why.
I sign in with thise code (code from internet not mine)
#Override
public void onStart() {
super.onStart();
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
GoogleSignInResult result = opr.get();
handleSignInResult(result);
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
// showProgressDialog();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
// hideProgressDialog();
handleSignInResult(googleSignInResult);
}
});
}
}
// [START onActivityResult]
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
// [END onActivityResult]
// [START handleSignInResult]
private void handleSignInResult(GoogleSignInResult result) {
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
mStatusTextView.setText(getString(R.string.signed_in_fmt, acct.getDisplayName()));
updateUI(true);
} else {
// Signed out, show unauthenticated UI.
updateUI(false);
}
}
// [END handleSignInResult]
// [START signIn]
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
// [END signIn]
// [START signOut]
private void signOut() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END signOut]
// [START revokeAccess]
private void revokeAccess() {
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// [START_EXCLUDE]
updateUI(false);
// [END_EXCLUDE]
}
});
}
// [END revokeAccess]
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// An unresolvable error has occurred and Google APIs (including Sign-In) will not
// be available.
}
private void showProgressDialog() {
if (mProgressDialog == null) {
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(true);
}
mProgressDialog.show();
}
private void hideProgressDialog() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.hide();
}
}
private void updateUI(boolean signedIn) {
if (signedIn) {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.VISIBLE);
} else {
mStatusTextView.setText(R.string.signed_out);
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_and_disconnect).setVisibility(View.GONE);
}
}
public void Login(){
// Views
mStatusTextView = (TextView) findViewById(R.id.status);
// Button listeners
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.disconnect_button).setOnClickListener(this);
// [START configure_signin]
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
// [END configure_signin]
// [START build_client]
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// [END build_client]
// [START customize_button]
// Customize sign-in button. The sign-in button can be displayed in
// multiple sizes and color schemes. It can also be contextually
// rendered based on the requested scopes. For example. a red button may
// be displayed when Google+ scopes are requested, but a white button
// may be displayed when only basic profile is requested. Try adding the
// Scopes.PLUS_LOGIN scope to the GoogleSignInOptions to see the
// difference.
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setScopes(gso.getScopeArray());
// [END customize_button]
}
I don't know what problem are crashed application because in genymotion i can't use login. and my mobile can't use adb driver. Please Help me.
or give mi advice where I can download runing code with leadherboards I will try understanding and use in my application.
Thanks.
Edit
Log? from firebase
Exception java.lang.IllegalStateException: GoogleApiClient is not configured to use the Games Api. Pass Games.API into GoogleApiClient.Builder#addApi() to use this feature.
com.google.android.gms.common.internal.zzaa.zza ()
com.google.android.gms.games.Games.zzc ()
com.google.android.gms.games.Games.zzb ()
com.google.android.gms.games.internal.api.LeaderboardsImpl.submitScore ()
com.google.android.gms.games.internal.api.LeaderboardsImpl.submitScore ()
sk.atest.paradox02.animacia.Index.onClick (Index.java:963)
android.view.View.performClick (View.java:5207)
android.view.View$PerformClick.run (View.java:21177)
android.os.Handler.handleCallback (Handler.java:739)
android.os.Handler.dispatchMessage (Handler.java:95)
android.os.Looper.loop (Looper.java:148)
android.app.ActivityThread.main (ActivityThread.java:5438)

DUPLICATE_REQUEST_ID - PayPal SDK error

Currently making an Android app and decided to integrate Paypal payment in it, so that the user is redirected to Paypal payment inside the app.
I found the Paypal SampleApp for what I want to do:
https://github.com/paypal/PayPal-Android-SDK.
Firstly, I tested it and it worked without errors with CONFIG_ENVIRONMENT set to PayPalConfiguration.ENVIRONMENT_NO_NETWORK, and with the default sandbox sample acc (usr: sample#buy.com, pass:123123123).
Then I made an account on developer.paypal.com in order to make the payment to my Paypal account (with CONFIG_ENVIRONMENT set to PayPalConfiguration.ENVIRONMENT_PRODUCTION). I created an app and used the provided Client ID from the developer portal in the SampleApp. By doing that, the payment isn't completed, and gives the error:
request failure with http statusCode:400,exception:Bad Request
request failed with server response:{"name":"DUPLICATE_REQUEST_ID","debug_id":"9f83f9a8ce3e5","message":"The value of PayPal-Request-Id header has already been used","information_link":"https://developer.paypal.com/webapps/developer/docs/api/","details":[]}
DUPLICATE_REQUEST_ID
Note: I'm only using the "BUY A THING" option in the Sample App; not interested in the other options
The code of the class that handles the payment process:
import com.paypal.android.sdk.payments.PayPalAuthorization;
import com.paypal.android.sdk.payments.PayPalConfiguration;
import com.paypal.android.sdk.payments.PayPalFuturePaymentActivity;
import com.paypal.android.sdk.payments.PayPalItem;
import com.paypal.android.sdk.payments.PayPalOAuthScopes;
import com.paypal.android.sdk.payments.PayPalPayment;
import com.paypal.android.sdk.payments.PayPalPaymentDetails;
import com.paypal.android.sdk.payments.PayPalProfileSharingActivity;
import com.paypal.android.sdk.payments.PayPalService;
import com.paypal.android.sdk.payments.PaymentConfirmation;
import com.paypal.android.sdk.payments.ShippingAddress;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import org.json.JSONException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class PaymentActivity extends Activity{
private static final String TAG = "PAYMENT";
private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION;
private static final String CONFIG_CLIENT_ID = "i changed this field with my client id";
private static final int REQUEST_CODE_PAYMENT = 1;
private static final int REQUEST_CODE_FUTURE_PAYMENT = 2;
private static final int REQUEST_CODE_PROFILE_SHARING = 3;
private static PayPalConfiguration config = new PayPalConfiguration()
.environment(CONFIG_ENVIRONMENT)
.clientId(CONFIG_CLIENT_ID)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment);
Intent intent = new Intent(this, PayPalService.class);
intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
startService(intent);
}
public void onBuyPressed(View pressed) {
PayPalPayment thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE);
Intent intent = new Intent(PaymentActivity.this, com.paypal.android.sdk.payments.PaymentActivity.class);
// send the same configuration for restart resiliency
intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
intent.putExtra(com.paypal.android.sdk.payments.PaymentActivity.EXTRA_PAYMENT, thingToBuy);
startActivityForResult(intent, REQUEST_CODE_PAYMENT);
}
private PayPalPayment getThingToBuy(String paymentIntent) {
return new PayPalPayment(new BigDecimal("1.0"), "USD", "DRINK",
paymentIntent);
}
/*
* This method shows use of optional payment details and item list.
*/
public void onFuturePaymentPressed(View pressed) {
Intent intent = new Intent(PaymentActivity.this, PayPalFuturePaymentActivity.class);
// send the same configuration for restart resiliency
intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
startActivityForResult(intent, REQUEST_CODE_FUTURE_PAYMENT);
}
public void onProfileSharingPressed(View pressed) {
Intent intent = new Intent(PaymentActivity.this, PayPalProfileSharingActivity.class);
// send the same configuration for restart resiliency
intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
intent.putExtra(PayPalProfileSharingActivity.EXTRA_REQUESTED_SCOPES, getOauthScopes());
startActivityForResult(intent, REQUEST_CODE_PROFILE_SHARING);
}
private PayPalOAuthScopes getOauthScopes() {
Set<String> scopes = new HashSet<String>(
Arrays.asList(PayPalOAuthScopes.PAYPAL_SCOPE_EMAIL, PayPalOAuthScopes.PAYPAL_SCOPE_ADDRESS) );
return new PayPalOAuthScopes(scopes);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PAYMENT) {
if (resultCode == Activity.RESULT_OK) {
PaymentConfirmation confirm =
data.getParcelableExtra(com.paypal.android.sdk.payments.PaymentActivity.EXTRA_RESULT_CONFIRMATION);
if (confirm != null) {
try {
Log.i(TAG, confirm.toJSONObject().toString(4));
Log.i(TAG, confirm.getPayment().toJSONObject().toString(4));
/**
* TODO: send 'confirm' (and possibly confirm.getPayment() to your server for verification
* or consent completion.
* See https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
* for more details.
*
* For sample mobile backend interactions, see
* https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
*/
Toast.makeText(
getApplicationContext(),
"PaymentConfirmation info received from PayPal", Toast.LENGTH_LONG)
.show();
} catch (JSONException e) {
Log.e(TAG, "an extremely unlikely failure occurred: ", e);
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "The user canceled.");
} else if (resultCode == com.paypal.android.sdk.payments.PaymentActivity.RESULT_EXTRAS_INVALID) {
Log.i(
TAG,
"An invalid Payment or PayPalConfiguration was submitted. Please see the docs.");
}
} else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) {
if (resultCode == Activity.RESULT_OK) {
PayPalAuthorization auth =
data.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION);
if (auth != null) {
try {
Log.i("FuturePaymentExample", auth.toJSONObject().toString(4));
String authorization_code = auth.getAuthorizationCode();
Log.i("FuturePaymentExample", authorization_code);
sendAuthorizationToServer(auth);
Toast.makeText(
getApplicationContext(),
"Future Payment code received from PayPal", Toast.LENGTH_LONG)
.show();
} catch (JSONException e) {
Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e);
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i("FuturePaymentExample", "The user canceled.");
} else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
Log.i(
"FuturePaymentExample",
"Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
}
} else if (requestCode == REQUEST_CODE_PROFILE_SHARING) {
if (resultCode == Activity.RESULT_OK) {
PayPalAuthorization auth =
data.getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION);
if (auth != null) {
try {
Log.i("ProfileSharingExample", auth.toJSONObject().toString(4));
String authorization_code = auth.getAuthorizationCode();
Log.i("ProfileSharingExample", authorization_code);
sendAuthorizationToServer(auth);
Toast.makeText(
getApplicationContext(),
"Profile Sharing code received from PayPal", Toast.LENGTH_LONG)
.show();
} catch (JSONException e) {
Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e);
}
}
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i("ProfileSharingExample", "The user canceled.");
} else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) {
Log.i(
"ProfileSharingExample",
"Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs.");
}
}
}
private void sendAuthorizationToServer(PayPalAuthorization authorization) {
/**
* TODO: Send the authorization response to your server, where it can
* exchange the authorization code for OAuth access and refresh tokens.
*
* Your server must then store these tokens, so that your server code
* can execute payments for this user in the future.
*
* A more complete example that includes the required app-server to
* PayPal-server integration is available from
* https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend
*/
}
#Override
public void onDestroy() {
// Stop service when done
stopService(new Intent(this, PayPalService.class));
super.onDestroy();
}
}
Thank you!
Turns out that the error occurs because the PayPal app is also installed on my phone. If I uninstall it, the payment is successfully done in the PRODUCTION environment.
PayPal will soon release a version of their app that patches this bug:
https://github.com/paypal/PayPal-Android-SDK/issues/272.

Categories