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.
Related
This is weird. I mean, I have strong network, and GPS is turned On, still it asks for Wifi !!
I'm using new Location Api with class FusedLocationProviderClient.
This is how I am checking if Location Settings are enabled or not:
private void checkIfLocationSettingsAreEnabled() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
SettingsClient client = LocationServices.getSettingsClient(context);
Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
getLastKnownLocation();
});
locationSettingsResponseTask.addOnFailureListener(e -> {
if (e instanceof ResolvableApiException) {
myLocationListener.onResolutionNeeded(e);
} else {
myLocationListener.onLocationFailure(e);
}
});
}
With the above code, I am able to get below image:
But then, after clicking OK, again I make call to checkIfSettingsAreEnabled() this shows another popup as below:
I wonder why enabling Wifi is mandatory, even if I am on desert safari, where there is no Wifi to connect to !!
Is there any way to Skip this Wifi option, and work as normal as Google Maps does ?
In fact, Google Maps uses priority PRIORITY_HIGH_ACCURACY and still once, the first settings dialog has been shown, it doesn't ask second time to turn on Wifi.
FusedLocationProvider uses a combo of GPS and WIFI to get your location. Especially when asking for balanced mode, it needs both or won't work (GPS takes power, so it won't rely just on it for balanced). Try max accuracy, its less likely to use it then. Or just use the GPS provider if you actually want GPS.
PRIORITY_BALANCED_POWER_ACCURACY
This priority will go with coarse level accuracy which fetch location only from wi-fi , cellular network or bluetooth and NOT from GPS.
and if device don't have SIM it needs to have wi-fi to get location or it will not call onLocationChanged till won't get location.
With the below solution, I am able to skip this Wifi Settings Dialog. This is not a perfect solution, but just a workaround till I find perfect solution.
Problem was, even after clicking "Ok" on Settings Dialog, it returned result as Activity.RESULT_CANCELLED. Reason was, Wifi was still turned off. So, as a quick fix, made a check in result Activity.RESULT_CANCELLED, that if I could get Location by checking LocationSettingStates.
You can use my MyLocationUtils.java and Base classes LocationActivity.java or LocationFragment.java. Happy Coding..!!
for getting location
MyLocationUtils.java:
public class MyLocationUtils {
public static final int REQUEST_CODE_LOCATION_SETTINGS = 123;
private static final int INTERVAL_IN_MS = 10000;
private static final int FASTEST_INTERVAL_IN_MS = 5000;
private static final int MAX_WAIT_TIME_IN_MS = 5000;
private static final int NUMBER_OF_UPDATES = 1;
private final MyLocationListener myLocationListener;
private final Context context;
private FusedLocationProviderClient mFusedLocationProviderClient;
private LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Location location = null;
if (locationResult.getLocations().size() > 0) {
location = locationResult.getLocations().get(0);
}
myLocationListener.onLocationSuccess(location);
stopContinuousLocation();
}
};
public MyLocationUtils(Context context, MyLocationListener myLocationListener) {
this.context = context;
this.myLocationListener = myLocationListener;
initializeFusedLocationProviderClient();
}
private boolean checkIfRequiredLocationSettingsAreEnabled(Context context) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private void initializeFusedLocationProviderClient() {
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
}
public void stopContinuousLocation() {
mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
}
public void getLocation() {
checkIfLocationSettingsAreEnabled();
}
private void checkIfLocationSettingsAreEnabled() {
if (checkIfRequiredLocationSettingsAreEnabled(context)) {
getLastKnownLocation();
} else {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(getLocationRequest());
builder.setAlwaysShow(true);
SettingsClient client = LocationServices.getSettingsClient(context);
Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
getLastKnownLocation();
});
locationSettingsResponseTask.addOnFailureListener(e -> {
if (e instanceof ResolvableApiException) {
myLocationListener.onResolutionNeeded(e);
} else {
myLocationListener.onLocationFailure(e);
}
});
}
}
#SuppressLint("MissingPermission")
private void getLastKnownLocation() {
Task<Location> locationTask = mFusedLocationProviderClient.getLastLocation();
locationTask.addOnSuccessListener(location -> {
// Got last known location. In some rare situations this can be null.
if (location != null) {
myLocationListener.onLocationSuccess(location);
} else {
startContinuousLocation();
}
});
locationTask.addOnFailureListener(myLocationListener::onLocationFailure);
}
#SuppressLint("MissingPermission")
private void startContinuousLocation() {
mFusedLocationProviderClient.requestLocationUpdates(getLocationRequest(), mLocationCallback, Looper.getMainLooper())
.addOnFailureListener(myLocationListener::onLocationFailure);
}
private LocationRequest getLocationRequest() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL_IN_MS);
locationRequest.setFastestInterval(FASTEST_INTERVAL_IN_MS);
locationRequest.setNumUpdates(NUMBER_OF_UPDATES);
locationRequest.setMaxWaitTime(MAX_WAIT_TIME_IN_MS);
return locationRequest;
}
public void resolveLocationSettings(FragmentActivity fragmentActivity, Exception exception) {
ResolvableApiException resolvable = (ResolvableApiException) exception;
try {
resolvable.startResolutionForResult(fragmentActivity, MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
public interface MyLocationListener {
void onLocationSuccess(Location location);
void onResolutionNeeded(Exception exception);
void onLocationFailure(Exception exception);
}
}
BaseLocationActivity.java:
public abstract class LocationActivity extends AppCompatActivity {
private MyLocationUtils myLocationUtils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myLocationUtils = new MyLocationUtils(this, new MyLocationUtils.MyLocationListener() {
#Override
public void onLocationSuccess(Location location) {
if (shouldBeAllowedToProceed())
LocationActivity.this.onLocationSuccess(location);
}
#Override
public void onResolutionNeeded(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationActivity.this.onResolutionNeeded(exception);
}
#Override
public void onLocationFailure(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationActivity.this.onLocationFailure(exception);
}
});
}
protected void getLocation() {
myLocationUtils.getLocation();
}
protected void resolveLocationSettings(Exception exception) {
myLocationUtils.resolveLocationSettings(this, exception);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
switch (resultCode) {
case Activity.RESULT_OK:
onResolveLocationSettingOk();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to,
// or on Android Oreo 8.1 Wifi Settings were not satisfied inspite of clicking OK, that results on Activity.RESULT_CANCELED
onResolveLocationSettingCancelled(locationSettingsStates);
break;
default:
break;
}
}
}
protected abstract void onResolveLocationSettingOk();
protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
onResolveLocationSettingOk();
}
}
private boolean shouldBeAllowedToProceed() {
return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
}
public abstract void onLocationSuccess(Location location);
public abstract void onResolutionNeeded(Exception exception);
public abstract void onLocationFailure(Exception exception);
#Override
public void onDestroy() {
super.onDestroy();
myLocationUtils.stopContinuousLocation();
}
}
LocationFragment.java:
public abstract class LocationFragment extends Fragment {
private MyLocationUtils myLocationUtils;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myLocationUtils = new MyLocationUtils(context, new MyLocationUtils.MyLocationListener() {
#Override
public void onLocationSuccess(Location location) {
if (shouldBeAllowedToProceed())
LocationFragment.this.onLocationSuccess(location);
}
#Override
public void onResolutionNeeded(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationFragment.this.onResolutionNeeded(exception);
}
#Override
public void onLocationFailure(Exception exception) {
exception.printStackTrace();
if (shouldBeAllowedToProceed())
LocationFragment.this.onLocationFailure(exception);
}
});
}
protected void resolveLocationSettings(FragmentActivity appCompatActivity, Exception exception) {
myLocationUtils.resolveLocationSettings(appCompatActivity, exception);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
switch (resultCode) {
case Activity.RESULT_OK:
onResolveLocationSettingOk();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
onResolveLocationSettingCancelled(locationSettingsStates);
break;
default:
break;
}
}
}
protected abstract void onResolveLocationSettingOk();
protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
onResolveLocationSettingOk();
}
}
public void getLocation() {
myLocationUtils.getLocation();
}
private boolean shouldBeAllowedToProceed() {
return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
}
public abstract void onLocationSuccess(Location location);
public abstract void onResolutionNeeded(Exception exception);
public abstract void onLocationFailure(Exception exception);
#Override
public void onDestroy() {
super.onDestroy();
myLocationUtils.stopContinuousLocation();
}
}
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 ,
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'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();
}
Currently I have 3 activities in my application. The first activity is to load default Splashscreen.class, I would like this activity to check whether the user accessed with your Google+ account "Sign In" on Login.class class.
In short, La Splashscreen.class class to check if the user logged in or not and direct it to one activity or another. I leave my code.
Splashscreen.class
public class SplashScreen extends Activity {
private boolean mIsBackButtonPressed;
private static final int SPLASH_DURATION = 2500;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
finish();
if (!mIsBackButtonPressed) {
/*if(){ If the user is connected go to class Mainactivity.class
Intent intent = new Intent(SplashScreen.this, MainActivity.class);
SplashScreen.this.startActivity(intent);
}
}else{
//If the user is not connected go to class Login.class
Intent intent = new Intent(SplashScreen.this, Login.class);
SplashScreen.this.startActivity(intent);
}
*/
}
}, SPLASH_DURATION);
}
#Override
public void onBackPressed() {
mIsBackButtonPressed = true;
super.onBackPressed();
}
}
Login.class
public class Login extends Activity implements OnPageChangeListener,GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, View.OnClickListener{
/* Request code used to invoke sign in user interactions. */
private static final int RC_SIGN_IN = 0;
static Context context;
/* Client used to interact with Google APIs. */
private static GoogleApiClient mGoogleApiClient;
/* A flag indicating that a PendingIntent is in progress and prevents
* us from starting further intents.
*/
private boolean mIntentInProgress;
private boolean mSignInClicked;
private ConnectionResult mConnectionResult;
boolean result_back;
private ViewPager vp;
private ViewPagerAdapter vpAdapter;
private List<View> views;
private ProgressDialog pDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
initViews();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
pDialog = new ProgressDialog(this);
pDialog.setMessage("Conectando ...");
findViewById(R.id.btn_sign_in).setOnClickListener(this);
}
public void onClick(View view) {
pDialog.show();
if (view.getId() == R.id.btn_sign_in
&& !mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInError();
}
}
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
public void onConnectionFailed(ConnectionResult result) {
if (!mIntentInProgress) {
// Store the ConnectionResult so that we can use it later when the user clicks
// 'sign-in'.
mConnectionResult = result;
if (mSignInClicked) {
// The user has already clicked 'sign-in' so we attempt to resolve all
// errors until the user is signed in, or they cancel.
resolveSignInError();
}
}
}
public void onConnected(Bundle connectionHint) {
// We've resolved any connection errors. mGoogleApiClient can be used to
// access Google APIs on behalf of the user.
pDialog.dismiss();
mSignInClicked = false;
//Toast.makeText(this, "User is connected!", Toast.LENGTH_SHORT).show();
getProfileInformation();
Intent i=new Intent(Login.this, MainActivity.class);
startActivity(i);
}
/**
* Fetching user's information name, email, profile pic
* */
public static void getProfileInformation() {
try {
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
Person currentPerson = Plus.PeopleApi
.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
currentPerson.getImage().getUrl();
currentPerson.getUrl();
Plus.AccountApi.getAccountName(mGoogleApiClient);
Toast.makeText(context,"Name: " + personName,Toast.LENGTH_LONG).show();
} else {
Toast.makeText(context,
"Person information is null", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == RC_SIGN_IN) {
if (responseCode != RESULT_OK) {
mSignInClicked = false;
}
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
}
public void onConnectionSuspended(int cause) {
mGoogleApiClient.connect();
}
private void resolveSignInError() {
if(mConnectionResult == null){
Toast.makeText(getApplicationContext(), "Es null", Toast.LENGTH_SHORT).show();
}else{
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
startIntentSenderForResult(mConnectionResult.getResolution().getIntentSender(),
RC_SIGN_IN, null, 0, 0, 0);
} 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();
}
}
}
}
private void initViews() {
LayoutInflater inflater = LayoutInflater.from(this);
views = new ArrayList<View>();
views.add(inflater.inflate(R.layout.layout_one, null));
views.add(inflater.inflate(R.layout.layout_two, null));
views.add(inflater.inflate(R.layout.layout_three, null));
vpAdapter = new ViewPagerAdapter(views, this);
vp = (ViewPager) findViewById(R.id.pager);
vp.setAdapter(vpAdapter);
vp.setOnPageChangeListener(this);
CirclePageIndicator indicator = (CirclePageIndicator)findViewById(R.id.circle);
indicator.setViewPager(vp);
indicator.setSnap(true);
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int arg0) {
}
}
Thank you all, Greetings!