public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
public static final int MASKED_WALLET_REQUEST_CODE = 888;
public static final String WALLET_FRAGMENT_ID = "wallet_fragment";
public static final int FULL_WALLET_REQUEST_CODE = 889;
private SupportWalletFragment mWalletFragment;
private MaskedWallet mMaskedWallet;
private GoogleApiClient mGoogleApiClient;
private FullWallet mFullWallet;
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WalletFragmentStyle walletFragmentStyle =
new WalletFragmentStyle().setBuyButtonText(BuyButtonText.BUY_NOW)
.setBuyButtonWidth(Dimension.MATCH_PARENT);
WalletFragmentOptions walletFragmentOptions = WalletFragmentOptions.newBuilder()
.setEnvironment(WalletConstants.ENVIRONMENT_SANDBOX)
.setFragmentStyle(walletFragmentStyle)
.setTheme(WalletConstants.THEME_LIGHT)
.setMode(WalletFragmentMode.BUY_BUTTON)
.build();
mWalletFragment = SupportWalletFragment.newInstance(walletFragmentOptions);
WalletFragmentInitParams.Builder startParamsBuilder = WalletFragmentInitParams.newBuilder()
.setMaskedWalletRequest(generateMaskedWalletRequest())
.setMaskedWalletRequestCode(MASKED_WALLET_REQUEST_CODE)
.setAccountName("Google I/O Codelab");
mWalletFragment.initialize(startParamsBuilder.build());
getSupportFragmentManager().beginTransaction()
.replace(R.id.wallet_button_holder, mWalletFragment, WALLET_FRAGMENT_ID)
.commit();
mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Wallet.API,
new Wallet.WalletOptions.Builder().setEnvironment(WalletConstants.ENVIRONMENT_SANDBOX)
.setTheme(WalletConstants.THEME_LIGHT)
.build())
.build();
}
public void requestFullWallet(View view) {
if (mMaskedWallet == null) {
Toast.makeText(this, "No masked wallet, can't confirm", Toast.LENGTH_SHORT).show();
return;
}
Wallet.Payments.loadFullWallet(mGoogleApiClient,
generateFullWalletRequest(mMaskedWallet.getGoogleTransactionId()),
FULL_WALLET_REQUEST_CODE);
}
#Override
public void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
public void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case MASKED_WALLET_REQUEST_CODE:
switch (resultCode) {
case Activity.RESULT_OK:
mMaskedWallet = data.getParcelableExtra(WalletConstants.EXTRA_MASKED_WALLET);
Toast.makeText(this, "Got Masked Wallet", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
// The user canceled the operation
break;
case WalletConstants.RESULT_ERROR:
Toast.makeText(this, "An Error Occurred", Toast.LENGTH_SHORT).show();
break;
case FULL_WALLET_REQUEST_CODE:
switch (resultCode) {
case Activity.RESULT_OK:
mFullWallet = data
.getParcelableExtra(WalletConstants.EXTRA_FULL_WALLET);
// Show the credit card number
Toast.makeText(this,
mFullWallet.getProxyCard().getPan().toString(),
Toast.LENGTH_SHORT).show();
Wallet.Payments.notifyTransactionStatus(mGoogleApiClient,
generateNotifyTransactionStatusRequest(
mFullWallet.getGoogleTransactionId(),
NotifyTransactionStatusRequest.Status.SUCCESS));
break;
case WalletConstants.RESULT_ERROR:
Toast.makeText(this, "An Error Occurred", Toast.LENGTH_SHORT).show();
break;
}
break;
}
break;
}
}
public static NotifyTransactionStatusRequest generateNotifyTransactionStatusRequest(
String googleTransactionId, int status) {
return NotifyTransactionStatusRequest.newBuilder()
.setGoogleTransactionId(googleTransactionId)
.setStatus(status)
.build();
}
private FullWalletRequest generateFullWalletRequest(String googleTransactionId) {
FullWalletRequest fullWalletRequest = FullWalletRequest.newBuilder()
.setGoogleTransactionId(googleTransactionId)
.setCart(Cart.newBuilder()
.setCurrencyCode("USD")
.setTotalPrice("10.10")
.addLineItem(LineItem.newBuilder()
.setCurrencyCode("USD")
.setDescription("Google I/O Sticker")
.setQuantity("1")
.setUnitPrice("10.00")
.setTotalPrice("10.00")
.build())
.addLineItem(LineItem.newBuilder()
.setCurrencyCode("USD")
.setDescription("Tax")
.setRole(LineItem.Role.TAX)
.setTotalPrice(".10")
.build())
.build())
.build();
return fullWalletRequest;
}
private MaskedWalletRequest generateMaskedWalletRequest() {
MaskedWalletRequest maskedWalletRequest = MaskedWalletRequest.newBuilder()
.setMerchantName("Google I/O Codelab")
.setPhoneNumberRequired(true)
.setShippingAddressRequired(true)
.setCurrencyCode("USD")
.setCart(Cart.newBuilder()
.setCurrencyCode("USD")
.setTotalPrice("10.00")
.addLineItem(LineItem.newBuilder()
.setCurrencyCode("USD")
.setDescription("Google I/O Sticker")
.setQuantity("1")
.setUnitPrice("10.00")
.setTotalPrice("10.00")
.build())
.build())
.setEstimatedTotalPrice("15.00")
.build();
return maskedWalletRequest;
}
#Override public void onConnected(Bundle bundle) {
}
#Override public void onConnectionSuspended(int i) {
}
#Override public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override public void onPointerCaptureChanged(boolean hasCapture) {
}
}
This code i have tried but i am able to run but i am not able to payment using Google wallet
i never try before Google wallet payment get-way please tell me how i will implement this is there any key or any other setting wee need use please help me.when i try to run this code and click on BuyNow then i am getting this payment options is no longer available in this app i dont know about how i will put what setting i need to set so that i should able to pay ,
Related
Hello I am building an app I would like to access the location of the mobile phone. However it seems that I can not grant the access fine location permission so my app doesn't function in Android M cellphone which I am testing.
Here is a part of my code:
public class LocationMainActivity extends AppCompatActivity {
private ListView listView;
private static final String EXTERNAL_PERMISSIONS[] = new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.INTERNET};
private static final int EXTERNAL_CODE=1;
private boolean perm;
private Cursor cursor;
private DatabaseAdapt dbAdapt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar4);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
listView = (ListView)findViewById(R.id.locationContainer);
dbAdapt = new DatabaseAdapt(this);
dbAdapt.open();
cursor =dbAdapt.loadLocationTitles();
String [] from = new String[]{DatabaseAdapt.LOCATION_TITLE};
int [] to = new int[] {android.R.id.text1};
CursorAdapter cursorAdapter = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,cursor,
from,to,0);
listView.setAdapter(cursorAdapter);
}
public void onDestroy(){
super.onDestroy();
cursor.close();
dbAdapt.close();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main,menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id==R.id.add_button);{
askForPerm();
if(perm){
Intent intent = new Intent(LocationMainActivity.this,LocationSecondActivity.class);
startActivity(intent);
}
else {
askForPerm();
}
}
return super.onOptionsItemSelected(item);
}
private void askForPerm () {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int w = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int r = ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET);
if (w != PackageManager.PERMISSION_GRANTED && r != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, EXTERNAL_PERMISSIONS, EXTERNAL_CODE);
} else {
Toast.makeText(this, "Permissions already granted", Toast.LENGTH_SHORT).show();
perm=true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case EXTERNAL_CODE:
if(ActivityCompat.checkSelfPermission(this,permissions[0])==PackageManager.PERMISSION_GRANTED)
{
perm=true;
}
else {
Toast.makeText(this,"Permissions denied",Toast.LENGTH_LONG).show();
perm=false;
}
break;
}
}
}
In this activity I ask for the permissions and only then I can add a new location. The app moves to the next activity regularly, the permissions granted toast is shown even I install the app for the first time which seems a little weird. I use the same code to request the Write External and camera permissions in another feature of the app and it is working fine.
I have also included the code of my second activity where I would like to obtain the location coordinates
private EditText editTitleLocation, addressText, latText,longText;
private Button saveLocationButton, deleteLocationButton, navigateButton,findLocationButton;
private static final int UPDATE_TIME = 15000;
private static final int FASTER_UPDATE_TIME = 10000;
private GoogleApiClient myGoogleApi;
private Location location;
private LocationRequest myLocationRequest;
private static final int CHECK_CODE=1;
private double longitude,latitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_location_second);
ActionBar actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
initializeViews();
buildGoogleApi();
}
private void initializeViews(){
editTitleLocation = (EditText)findViewById(R.id.editTitleLocation);
addressText = (EditText)findViewById(R.id.addressText);
latText = (EditText)findViewById(R.id.latitudeText);
longText=(EditText)findViewById(R.id.longitudeText);
saveLocationButton = (Button)findViewById(R.id.saveLocation);
deleteLocationButton = (Button)findViewById(R.id.deleteLocation);
findLocationButton = (Button)findViewById(R.id.findLocation);
navigateButton= (Button)findViewById(R.id.navigateLocation);
saveLocationButton.setOnClickListener(this);
deleteLocationButton.setOnClickListener(this);
findLocationButton.setOnClickListener(this);
navigateButton.setOnClickListener(this);
}
public void onStart(){
super.onStart();
if(myGoogleApi!=null){
myGoogleApi.connect();
}
}
public void onPause(){
super.onPause();
if(myGoogleApi!=null)
LocationServices.FusedLocationApi.removeLocationUpdates(myGoogleApi,LocationSecondActivity.this);
}
public void onStop(){
super.onStop();
myGoogleApi.disconnect();
}
private synchronized void buildGoogleApi(){
myGoogleApi = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
private void createRequest (){
myLocationRequest = new LocationRequest();
myLocationRequest.setInterval(UPDATE_TIME)
.setFastestInterval(FASTER_UPDATE_TIME)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(myLocationRequest);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(myGoogleApi,builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()){
case LocationSettingsStatusCodes.SUCCESS:
retrieveLocation();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try{
status.startResolutionForResult(LocationSecondActivity.this,CHECK_CODE);
}catch (IntentSender.SendIntentException e){
e.printStackTrace();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Toast.makeText(LocationSecondActivity.this,"Settings Change Unavailable",Toast.LENGTH_SHORT).show();
break;
}
}
});
}
private void retrieveLocation(){
try {
location = LocationServices.FusedLocationApi.getLastLocation(myGoogleApi);
}catch (SecurityException ex){
ex.printStackTrace();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case CHECK_CODE:
switch (requestCode){
case Activity.RESULT_OK:
retrieveLocation();
break;
case Activity.RESULT_CANCELED:
break;
}
break;
}
}
#Override
public void onConnected(Bundle bundle) {
createRequest();
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Toast.makeText(this,"Google Api can not connect",Toast.LENGTH_LONG).show();
}
#Override
public void onLocationChanged(Location location) {
this.location=location;
longitude=location.getLongitude();
latitude=location.getLatitude();
}
#Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.saveLocation:
break;
case R.id.deleteLocation:
break;
case R.id.navigateLocation:
break;
case R.id.findLocation:
if(location!=null){
latitude = location.getLatitude();
Log.e("MALAKIS",String.valueOf(latitude));
longitude=location.getLongitude();
latText.setText(String.valueOf(latitude));
longText.setText(String.valueOf(longitude));
}else {
if(!myGoogleApi.isConnected()){
myGoogleApi.connect();
Log.e("ELSE","fdsfddsd");
}
try {
LocationServices.FusedLocationApi.requestLocationUpdates(myGoogleApi, myLocationRequest, this);
}catch (SecurityException ex){
ex.printStackTrace();
}
}
break;
}
}
Here the location is object is null and the security location is triggered pointing that I dont have the fine location permission. So please can someone point me to the right direction? Do I have do ask again for permissions in the second activity?
The log is showing this below:
W/System.err: java.lang.SecurityException: Client must have
ACCESS_FINE_LOCATION permission to request PRIORITY_HIGH_ACCURACY
locations.
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at android.os.Parcel.readException(Parcel.java:1602)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at android.os.Parcel.readException(Parcel.java:1555)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at
com.google.android.gms.internal.zzase$zza$zza.zza(Unknown Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at com.google.android.gms.internal.zzasg.zza(Unknown
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at com.google.android.gms.internal.zzash.zza(Unknown
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at com.google.android.gms.internal.zzary$1.zza(Unknown
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at com.google.android.gms.internal.zzary$1.zza(Unknown
Source)
05-30 10:50:40.516 32177-32177/com.example.notepad.isidorosioannou.notepad
W/System.err: at com.google.android.gms.internal.zzaad$zza.zzb(Unknown
Source)
put following code in your askForPerm () method:-
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true); //this is the key ingredient
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
Try this!!It works in my application.
I'm trying to submit a highscore to my leaderboards, but for some reason it doesn't work. The app doesn't crash and there is no error in the logcat.
When the user isn't logged in there will be a pop-up of Google Play Games. Currently when a user gets a new highscore the app automatically shows the toast. So it seems my Asynctask is not correctly coded?
public class result extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks{
public GoogleApiClient mGoogleApiClient;
private static int RC_SIGN_IN = 9001;
private boolean mResolvingConnectionFailure = false;
private boolean mAutoStartSignInFlow = true;
private boolean mSignInClicked = false;
public int HighScore;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
// Create the Google Api Client with access to the Play Games services
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
// add other APIs and scopes here as needed
.build();
TextView scoreLabel = (TextView) findViewById(R.id.scoreLabel);
TextView highScoreLabel = (TextView) findViewById(R.id.highScoreLabel);
int score = getIntent().getIntExtra("SCORE", 0);
scoreLabel.setText(score + "");
SharedPreferences settings = getSharedPreferences("HIGH_SCORE", Context.MODE_PRIVATE);
HighScore = settings.getInt("HIGH_SCORE", 0);
if (score > HighScore) {
highScoreLabel.setText("High Score : " + score);
submitScore(score);
// Update High Score
SharedPreferences.Editor editor = settings.edit();
editor.putInt("HIGH_SCORE", score);
editor.commit();
} else {
highScoreLabel.setText("High Score : " + HighScore);
}
}
public void tryAgain(View view) {
startActivity(new Intent(getApplicationContext(), start.class));
}
// Disable Return Button
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK:
return true;
}
}
return super.dispatchKeyEvent(event);
}
public class LoadData extends AsyncTask<Void, Void, Void> {
ProgressDialog pdLoading = new ProgressDialog(result.this);
//declare other objects as per your need
#Override
protected void onPreExecute()
{
pdLoading.setMessage("\tSending highscore to leaderboard...");
pdLoading.show();
//do initialization of required objects objects here
};
#Override
protected Void doInBackground(Void... params)
{
Games.Leaderboards.submitScoreImmediate(mGoogleApiClient, getString(R.string.leaderboard_top_players), HighScore);
//do loading operation here
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pdLoading.dismiss();
};
}
//Start GPS
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
// Attempt to reconnect
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (mResolvingConnectionFailure) {
// Already resolving
return;
}
// If the sign in button was clicked or if auto sign-in is enabled,
// launch the sign-in flow
if (mSignInClicked || mAutoStartSignInFlow) {
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = true;
// Attempt to resolve the connection failure using BaseGameUtils.
// The R.string.signin_other_error value should reference a generic
// error string in your strings.xml file, such as "There was
// an issue with sign in, please try again later."
if (!BaseGameUtils.resolveConnectionFailure(this,
mGoogleApiClient, connectionResult,
RC_SIGN_IN, getString(R.string.signin_other_error))) {
mResolvingConnectionFailure = false;
}
}
// Put code here to display the sign-in button
}
public void submitScore(long highscore){
if (mGoogleApiClient.isConnected()){
LoadData task = new LoadData();
task.execute();
//Games.Leaderboards.submitScoreImmediate(mGoogleApiClient, getString(R.string.leaderboard_top_players), highscore);
}else{
Toast.makeText(this, "Unable to submit highscore", Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (requestCode == RC_SIGN_IN) {
mSignInClicked = false;
mResolvingConnectionFailure = false;
if (resultCode == RESULT_OK) {
mGoogleApiClient.connect();
} else {
// Bring up an error dialog to alert the user that sign-in
// failed. The R.string.signin_failure should reference an error
// string in your strings.xml file that tells the user they
// could not be signed in, such as "Unable to sign in."
BaseGameUtils.showActivityResultError(this,
requestCode, resultCode, R.string.signin_failure);
}
}
}
}
You seem to be declaring mGoogleAPIClient but not actually creating an instance of it, hence your 'NullPointerException'
Before you try to use mGoogleAPIClient, add the following to create it.....
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
// add other APIs and scopes here as needed
.build();
See Here for more details
Hope this helps
I am trying to let the user login in my app with his google account.
I setup the client id in the google developer console, with the package name and the sha1 of my debug keystore, enabled the google plus api and filled in the consent screen.
Here is the code of the activity which perform the login with googleApiClient:
public class IntroActivity extends BaseActivity implements
LoginFragment.FragmentListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
private static final int RC_GOOGLE_SIGN_IN = 0;
private GoogleApiClient googleApiClient;
private boolean intentInProgress;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
if (savedInstanceState == null) {
LoginFragment loginFragment = new LoginFragment();
replaceFragment(loginFragment, false);
}
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
}
#Override
protected void onStop() {
super.onStop();
if (googleApiClient.isConnected()) {
googleApiClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
switch (requestCode) {
case RC_GOOGLE_SIGN_IN:
intentInProgress = false;
if (!googleApiClient.isConnecting()) {
googleApiClient.connect();
}
break;
}
}
#Override
public void onGoogleSignInClick() {
googleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
if (Plus.PeopleApi.getCurrentPerson(googleApiClient) != null) {
String email = Plus.AccountApi.getAccountName(googleApiClient);
String token = null;
try {
token = GoogleAuthUtil.getToken(this, email, Plus.SCOPE_PLUS_LOGIN.toString());
} catch (IOException | GoogleAuthException e) {
e.printStackTrace();
}
showShortToast(token);
}
}
#Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (!intentInProgress && connectionResult.hasResolution()) {
try {
intentInProgress = true;
startIntentSenderForResult(connectionResult.getResolution().getIntentSender(), RC_GOOGLE_SIGN_IN, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
intentInProgress = false;
googleApiClient.connect();
}
} else {
showShortToast("onConnectionFailed");
}
}
}
As soon as the googleApiClient starts connecting, it fails to connect and it displays a popup in order to choose the account. Once selected, it still goes in onConnectionFailed method, but this time seems there is no resolution for the problem.
The ConnectionResult get {statusCode=SIGN_IN_FAILED, resolution=null}
Why I get sign in failed? Is it possible that the app is not linked with the project on the dev console somehow?
I have the following code where it does two main things.
It connects to google play services.
Inside the onConnected() method a service is started, by calling the startService(...) method.
When I run the program I get the following log message.
Connected!!!
Fit wasn't able to connect, so the request failed.
GoogleFitService destroyed.
Here is my code:
public class MainActivity extends ActionBarActivity {
public final static String TAG = "GoogleFitService";
private static final int REQUEST_OAUTH = 1;
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buildFitnessClient();
}
private void buildFitnessClient() {
// Create the Google API Client
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
Intent service = new Intent(MainActivity.this,
GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE,
GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
public void onConnectionSuspended(int i) {
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
return;
}
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
mClient.connect();
Intent service = new Intent(this, GoogleFitService.class);
service.putExtra(GoogleFitService.SERVICE_REQUEST_TYPE, GoogleFitService.TYPE_REQUEST_CONNECTION);
startService(service);
}
#Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
}
And the second class is basically an Intent service. Maybe the mistake is here.
public class GoogleFitService extends IntentService {
public static final String TAG = "GoogleFitService";
private GoogleApiClient mGoogleApiFitnessClient;
private boolean mTryingToConnect = false;
public static final String SERVICE_REQUEST_TYPE = "requestType";
public static final int TYPE_GET_STEP_TODAY_DATA = 1;
public static final int TYPE_REQUEST_CONNECTION = 2;
public static final String HISTORY_INTENT = "fitHistory";
public static final String HISTORY_EXTRA_STEPS_TODAY = "stepsToday";
public static final String FIT_NOTIFY_INTENT = "fitStatusUpdateIntent";
public static final String FIT_EXTRA_CONNECTION_MESSAGE =
"fitFirstConnection";
public static final String FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE =
"fitExtraFailedStatusCode";
public static final String FIT_EXTRA_NOTIFY_FAILED_INTENT =
"fitExtraFailedIntent";
#Override
public void onDestroy() {
Log.d(TAG, "GoogleFitService destroyed");
if (mGoogleApiFitnessClient.isConnected()) {
Log.d(TAG, "Disconecting Google Fit.");
mGoogleApiFitnessClient.disconnect();
}
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
buildFitnessClient();
Log.d(TAG, "GoogleFitService created");
}
public GoogleFitService() {
super("GoogleFitService");
}
#Override
protected void onHandleIntent(Intent intent) {
//Get the request type
int type = intent.getIntExtra(SERVICE_REQUEST_TYPE, 1);
//block until google fit connects. Give up after 10 seconds.
if (!mGoogleApiFitnessClient.isConnected()) {
mTryingToConnect = true;
mGoogleApiFitnessClient.connect();
//Wait until the service either connects or fails to connect
while (mTryingToConnect) {
try {
Thread.sleep(100, 0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
if (mGoogleApiFitnessClient.isConnected()) {
if (type == TYPE_GET_STEP_TODAY_DATA) {
Log.d(TAG, "Requesting steps from Google Fit");
getStepsToday();
Log.d(TAG, "Fit update complete. Allowing Android to destroy
the service.");
} else if (type == TYPE_REQUEST_CONNECTION) {
}
} else {
//Not connected
Log.w(TAG, "Fit wasn't able to connect, so the request failed.");
}
}
private void getStepsToday() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
long startTime = cal.getTimeInMillis();
final DataReadRequest readRequest = new DataReadRequest.Builder()
.read(DataType.TYPE_STEP_COUNT_DELTA)
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
.build();
DataReadResult dataReadResult =
Fitness.HistoryApi.readData(mGoogleApiFitnessClient,
readRequest).await(1, TimeUnit.MINUTES);
DataSet stepData =
dataReadResult.getDataSet(DataType.TYPE_STEP_COUNT_DELTA);
int totalSteps = 0;
for (DataPoint dp : stepData.getDataPoints()) {
for (Field field : dp.getDataType().getFields()) {
int steps = dp.getValue(field).asInt();
totalSteps += steps;
}
}
publishTodaysStepData(totalSteps);
}
private void publishTodaysStepData(int totalSteps) {
Intent intent = new Intent(HISTORY_INTENT);
// You can also include some extra data.
intent.putExtra(HISTORY_EXTRA_STEPS_TODAY, totalSteps);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void buildFitnessClient() {
// Create the Google API Client
mGoogleApiFitnessClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Google Fit connected.");
mTryingToConnect = false;
Log.d(TAG, "Notifying the UI that we're
connected.");
notifyUiFitConnected();
}
#Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at
some point,
mTryingToConnect = false;
if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Google Fit Connection lost.
Cause:Network Lost.");
} else if (i ==
GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Google Fit Connection lost.
Reason:Service Disconnected ");
}
}
}
)
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult
result) {
mTryingToConnect = false;
notifyUiFailedConnection(result);
}
}
)
.build();
}
private void notifyUiFitConnected() {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_CONNECTION_MESSAGE,
FIT_EXTRA_CONNECTION_MESSAGE);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void notifyUiFailedConnection(ConnectionResult result) {
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE,
result.getErrorCode());
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
Any ideas what might went wrong? Thanks, Theo.
You need to access those detail from fit only when it connected .And Try this
public void buildFitnessClient() {
fitnessClient = new GoogleApiClient.Builder(context)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.SESSIONS_API)
.addApi(Fitness.RECORDING_API)
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE))
.addConnectionCallbacks(
new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
ReferenceWrapper.getInstance(context).setApiClient(fitnessClient);
((OnClientConnectListener) context).onclientConnected();
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(
new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(
ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(
result.getErrorCode(), context, 0)
.show();
return;
}
if (!authInProgress) {
try {
authInProgress = true;
result.startResolutionForResult(
context,
KeyConstant.REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
}
}
}
}).build();
}
And at first you need to register your application on google api console . Generate an outh2 client id from there and enable fitness api . Search for fitness Api in api Dashboard , and enable it.. And override OnActivityresult
in your Activity .
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == KeyConstant.REQUEST_OAUTH) {
fitnessHelper.setAuthInProgress(false);
if (resultCode == Activity.RESULT_OK) {
if (!fitnessHelper.isConnecting() && !fitnessHelper.isConnected()) {
fitnessHelper.connect();
}
}
}
}
I'm trying to carry out the Google Plus login within my app but no matter what I do, if the Scope is set to Plus.SCOPE_PLUS_LOGIN, I always get a ConnectionResult whose ErrorCode is 17 (SIGN_IN_FAILED). On the other hand, if I pick Plus.SCOPE_PLUS_PROFILE the app gets connected but when I retrieve the Person object, this one is always null.
I have created a new project in the developer console, enable the Google+ API and created a Cliend ID that includes the proper SHA1 fingerprint for the debug version of the app and its package. I have also picked an email and product name.
I have also tried to rename the package of the app and update the project in the developer console, but I still get the same error.
The thing is that I have downloaded the Google example, created a project in my developer console for it and it works... but when I try to use the same class that does the job in my app, it always fails... really weird. I have also checked the Google + API usage section and it never handles any request sent by my app... whereas it does it for the Google example...
This is the code of the class that carries out the whole process.. as you can see it looks practically the same as the one in the Google example...
public class MainActivity extends FragmentActivity implements
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult>, View.OnClickListener {
private static final int STATE_DEFAULT = 0;
private static final int STATE_SIGN_IN = 1;
private static final int STATE_IN_PROGRESS = 2;
private static final int RC_SIGN_IN = 0;
private static final int DIALOG_PLAY_SERVICES_ERROR = 0;
private static final String SAVED_PROGRESS = "sign_in_progress";
private int mSignInError;
private SignInButton mSignInButton;
private Button mSignOutButton;
private Button mRevokeButton;
private TextView mStatus;
private ListView mCirclesListView;
private ArrayAdapter<String> mCirclesAdapter;
private ArrayList<String> mCirclesList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSignInButton = (SignInButton) findViewById(R.id.sign_in_button);
mSignOutButton = (Button) findViewById(R.id.sign_out_button);
mRevokeButton = (Button) findViewById(R.id.revoke_access_button);
mStatus = (TextView) findViewById(R.id.sign_in_status);
mCirclesListView = (ListView) findViewById(R.id.circles_list);
mSignInButton.setOnClickListener(this);
mSignOutButton.setOnClickListener(this);
mRevokeButton.setOnClickListener(this);
mCirclesList = new ArrayList<String>();
mCirclesAdapter = new ArrayAdapter<String>(
this, R.layout.circle_member, mCirclesList);
mCirclesListView.setAdapter(mCirclesAdapter);
if (savedInstanceState != null) {
mSignInProgress = savedInstanceState
.getInt(SAVED_PROGRESS, STATE_DEFAULT);
}
mGoogleApiClient = buildGoogleApiClient();
}
private GoogleApiClient buildGoogleApiClient() {
return new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
//.addScope(Plus.SCOPE_PLUS_PROFILE)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SAVED_PROGRESS, mSignInProgress);
}
#Override
public void onClick(View v) {
if (!mGoogleApiClient.isConnecting()) {
switch (v.getId()) {
case R.id.sign_in_button:
mStatus.setText("Sign in");
resolveSignInError();
break;
case R.id.sign_out_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
break;
case R.id.revoke_access_button:
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient);
mGoogleApiClient = buildGoogleApiClient();
mGoogleApiClient.connect();
break;
}
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "onConnected");
mSignInButton.setEnabled(false);
mSignOutButton.setEnabled(true);
mRevokeButton.setEnabled(true);
Person currentUser = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
Log.d("profile", "profile, name: " + currentUser.getName() + ", id: " + currentUser.getId());
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
mStatus.setText(String.format("Sign in",
email));
Plus.PeopleApi.loadVisible(mGoogleApiClient, null)
.setResultCallback(this);
mSignInProgress = STATE_DEFAULT;
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "onConnectionFailed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
if (result.getErrorCode() == ConnectionResult.API_UNAVAILABLE) {
} else if (mSignInProgress != STATE_IN_PROGRESS) {
mSignInIntent = result.getResolution();
mSignInError = result.getErrorCode();
if (mSignInProgress == STATE_SIGN_IN) {
resolveSignInError();
}
}
onSignedOut();
}
private void resolveSignInError() {
if (mSignInIntent != null) {
try {
mSignInProgress = STATE_IN_PROGRESS;
startIntentSenderForResult(mSignInIntent.getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "Sign in intent could not be sent: "
+ e.getLocalizedMessage());
mSignInProgress = STATE_SIGN_IN;
mGoogleApiClient.connect();
}
} else {
showDialog(DIALOG_PLAY_SERVICES_ERROR);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
switch (requestCode) {
case RC_SIGN_IN:
if (resultCode == RESULT_OK) {
mSignInProgress = STATE_SIGN_IN;
} else {
mSignInProgress = STATE_DEFAULT;
}
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
break;
}
}
#Override
public void onResult(People.LoadPeopleResult peopleData) {
if (peopleData.getStatus().getStatusCode() == CommonStatusCodes.SUCCESS) {
mCirclesList.clear();
PersonBuffer personBuffer = peopleData.getPersonBuffer();
try {
int count = personBuffer.getCount();
for (int i = 0; i < count; i++) {
mCirclesList.add(personBuffer.get(i).getDisplayName());
}
} finally {
personBuffer.close();
}
mCirclesAdapter.notifyDataSetChanged();
} else {
Log.e(TAG, "Error requesting visible circles: " + peopleData.getStatus());
}
}
private void onSignedOut() {
mSignInButton.setEnabled(true);
mSignOutButton.setEnabled(false);
mRevokeButton.setEnabled(false);
mStatus.setText("Sign out");
mCirclesList.clear();
mCirclesAdapter.notifyDataSetChanged();
}
#Override
public void onConnectionSuspended(int cause) {
ConnectionResult that we can attempt to resolve.
mGoogleApiClient.connect();
}