I have been trying to learn how to use the GCM by going over their step by step guild. I get to the point of registering but it never actually does the registration part of the project. I have the configuration file in the project and I am using this website to test for push notification http://www.androidbegin.com/tutorial/gcm.html
So this is what it is giving me in the logcat:
02-18 14:07:42.866 32402-32402/com.example.mmillar.gcmpushnotificationtest D/Main Activity: Started
02-18 14:07:42.867 32402-32402/com.example.mmillar.gcmpushnotificationtest D/Checking PlayService: Started
02-18 14:07:42.868 32402-32402/com.example.mmillar.gcmpushnotificationtest D/Cheking player Service: true
02-18 14:07:42.868 32402-32402/com.example.mmillar.gcmpushnotificationtest D/Starting service:: Intent { cmp=com.example.mmillar.gcmpushnotificationtest/.Registration }
02-18 14:07:42.877 32402-32432/com.example.mmillar.gcmpushnotificationtest D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
02-18 14:07:42.949 32402-32432/com.example.mmillar.gcmpushnotificationtest I/OpenGLRenderer: Initialized EGL, version 1.4
02-18 14:07:43.008 32402-32432/com.example.mmillar.gcmpushnotificationtest W/EGL_emulation: eglSurfaceAttrib not implemented
02-18 14:07:43.008 32402-32432/com.example.mmillar.gcmpushnotificationtest W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xad79f100, error=EGL_SUCCESS
02-18 14:07:45.679 32402-32407/com.example.mmillar.gcmpushnotificationtest W/art: Suspending all threads took: 12.876ms
02-18 14:07:53.143 32402-32429/com.example.mmillar.gcmpushnotificationtest I/GMPM: Tag Manager is not found and thus will not be used
02-18 14:08:33.167 32402-32411/com.example.mmillar.gcmpushnotificationtest W/art: Suspending all threads took: 5.121ms
02-18 14:10:19.493 32402-32407/com.example.mmillar.gcmpushnotificationtest W/art: Suspending all threads took: 6.036ms
02-18 14:11:15.635 32402-32407/com.example.mmillar.gcmpushnotificationtest W/art: Suspending all threads took: 12.898ms
As it shows it get down to the start(intent0 part of the onCreate method. But it never reaches to the Register class at all. I am a bit stumped on what I am doing wrong here. Any help will be appreciated.
here is the main activity code that starts the app
public class GCMMainActivity extends AppCompatActivity{
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
private static final String TAG = "MainActivity";
private BroadcastReceiver mRegistrationBroadcastReceiver;
private ProgressBar mRegistrationProgressBar;
private TextView mInformationTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gcmmain);
Log.d("Main Activity", "Started");
mRegistrationProgressBar = (ProgressBar) findViewById(R.id.registrationProgressBar);
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Main Activity: ", "onReceive Method");
mRegistrationProgressBar.setVisibility(ProgressBar.GONE);
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context);
boolean sentToken = sharedPreferences.getBoolean(Preferences.SENT_TOKEN_TO_SERVER, false);
if (sentToken) {
mInformationTextView.setText("Token retrieved and sent to server! You can now use gcmsender to\n" +
" send downstream messages to this app");
} else {
mInformationTextView.setText("An error occurred while either fetching the InstanceID token,\n" +
"sending the fetched token to the server or subscribing to the PubSub topic. ");
}
}
};
mInformationTextView = (TextView) findViewById(R.id.informationTextView);
if (checkPlayServices()) {
Log.d("Checking PlayService", "Started");
Boolean check = checkPlayServices();
Log.d("Cheking player Service ", check.toString());
// Start IntentService to register this application with GCM.
Intent intent = new Intent(this, Registration.class);
//this should call the registration code
Log.d("Starting service: ", intent.toString());
startService(intent);
}
}
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
new IntentFilter(Preferences.REGISTRATION_COMPLETE));
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
super.onPause();
}
//deos the device support google play?
private boolean checkPlayServices() {
GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();
int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (apiAvailability.isUserResolvableError(resultCode)) {
apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)
.show();
} else {
Log.d(TAG, "This device is not supported.");
finish();
}
return false;
}
return true;
}
}
And this is the registration class
public class Registration extends IntentService {
private static final String TAG = "RegIntentService";
private static final String[] TOPICS = {"global"};
private final String SENDERID = "630172590481";
public Registration() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("Registration Class: ", "onHandleIntent mehtod");
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
//Register for the gcm
try {
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
InstanceID instanceID = InstanceID.getInstance(this);
//this is using the google configuration file crated at their website
//https://developers.google.com/cloud-messaging/android/start
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
/*used to hardcode the Sender ID
String token = instanceID.getToken(SENDERID),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
*/
Log.d(TAG, "GCM Registration Token: " + token);
sendRegistrationToServer(token);
// Subscribe to topic channels
subscribeTopics(token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(Preferences.SENT_TOKEN_TO_SERVER, true).apply();
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// update at a later time.
sharedPreferences.edit().putBoolean(Preferences.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(Preferences.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
//Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
private void subscribeTopics(String token) throws IOException {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
for (String topic : TOPICS) {
pubSub.subscribe(token, "/topics/" + topic, null);
}
}
}
Related
Here is the situation:
When a user creates a Geofence, I save it to backend and I register a Geofence with the OS. But whenever my app restarts I fetch geofences from my backend and reregister them with the OS again, since they keep disappearing.
I have two classes MainActivity and FormActivity. Both of these activities register Geofences, so I have extracted the actual registration to an ordinary POJO Geofences.java
Here is the problem:
Now the strange thing is, triggers are only received when a map activity is on the screen. I do have a map activity in my app, but it doesn't even have to be my map-activity, even if I launch google maps geofence triggers start firing.
What am I doing wrong?
Geofences.java:
public class Geofences {
private final String TAG = Geofences.class.getSimpleName();
private final float RADIUS = 150.0F; //meter
private boolean success = false;
private final int LOITERING_IN_MILLISECONDS = 30000;// 30 seconds
public boolean doGeofenceStuff(GeoTemp newTemp, String geofenceId, PendingIntent pendingIntent, GeofencingClient geofencingClient) {
Geofence geofence = createGeofence(newTemp, geofenceId);
GeofencingRequest geofencingRequest = createGeofenceRequest(geofence);
geofencingClient.addGeofences(geofencingRequest, pendingIntent)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
success = true;
Log.i(TAG, "onComplete: DEBUG-Message: Geofence has been added.");
} else {
success = false;
Log.i(TAG, "onComplete: Geofence could not be added");
}
}
}); // handle error here
return success;
}
// Create a Geofence
private Geofence createGeofence(GeoTemp geoTemp, String geofenceId) {
long expiration = getExpirationForCurrentGeofence();
if (expiration < 1) {
Log.e(TAG, "createGeofence: Can't create Geofence, since expiration is less than zero");
return null;
}
Log.d(TAG, "createGeofence");
return new Geofence.Builder()
.setRequestId(geofenceId)
.setCircularRegion(getLat(), getLong(), RADIUS)
.setExpirationDuration(expiration)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT)
.setLoiteringDelay(LOITERING_IN_MILLISECONDS)
.build();
}
// Create a Geofence Request
private GeofencingRequest createGeofenceRequest(Geofence geofence) {
Log.d(TAG, "createGeofenceRequest");
return new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_DWELL)
.addGeofence(geofence)
.build();
}
}
This POJO Geofences.java is then used by two of my activities:
MainActivity:
public class MainActivity extends AppCompatActivity {
private static String TAG = "MainActivity";
private final int GEOFENCE_REQ_CODE = 0;
private GeofencingClient geofencingClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
geofencingClient = LocationServices.getGeofencingClient(this);
getCurrentTemps();
}
private void refreshGeofence(GeoTemp temp, String id) {
new Geofences().doGeofenceStuff(temp, id, createGeofencePendingIntent(), geofencingClient);
}
private void getCurrentTemps() {
List<GeoTemp> currentGeofences = getUpdatedList();
currentGeofences.forEach(geoTemp -> {
refreshGeofence( geoTemp, id);
});
}
private PendingIntent createGeofencePendingIntent() {
Log.d(TAG, "createGeofencePendingIntent");
Intent intent = new Intent(this, LocationAlertIntentService.class);
return PendingIntent.getService(
this, GEOFENCE_REQ_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
There is one more activity which uses Geofences.java to register geofences with the operating system.
Update:
I have found out that, if any other app (including mine) requests for location lock, geofence triggers fire. I need them to fire in the background.
I had similar issue when working with geofencing in android.
This happens due to background restrictions added in Android Oreo and later.
OS does not allow your app to start service when it is in background so you won't receive geofence trigger.
To handle this:
Add broadcast receiver to receive intent. (This receiver will get
geofence alert even when app is in background)
Replace service with JobIntentService. (This will use OS JobSchedular
and run even with background restrictions)
Get broadcast from pending intent instead of service.
Checkout this sample project for further clarifications.
I have implemented a ANR watchdog in my application using this GitHub repo. The watchdog monitors the UI thread and if it is blocked for more than 10 seconds, if restarts the app. My problem is it restarts the app twice, thus messing with all my logic.
This is my implementation of the WatchDog :
public class ANRWatchdog extends Thread {
private final Handler uiHandler = new Handler(Looper.getMainLooper());
private int count = 0; //
private static final int DEFAULT_WAIT_TIME = 10000; // in milliseconds
private volatile boolean anr = false;
private Context context;
public ANRWatchdog(Context context) {
super();
this.context = context;
}
private final Runnable counter = () -> count = (count + 1) % Integer.MAX_VALUE;
#Override
public void run() {
setName("WatchDog");
int lastCount;
while (!isInterrupted()) {
if ( anr){
anr = false;
return;
}
lastCount = count;
uiHandler.post(counter);
try {
Thread.sleep(DEFAULT_WAIT_TIME);
} catch (InterruptedException e) {
Log.e("WatchDog",
"Error while making the ANR thread sleep" + e);
return;
}
if (count == lastCount) {// means the value hasn't been incremented. UI thread has been blocked
anr = true;
Log.d("WatchDog", "Count hasn't incremented. This means ANR. Will restart the app. Thread Id : " +
android.os.Process.getThreadPriority(android.os.Process.myTid()));
uiHandler.removeCallbacks(counter, null);
uiHandler.removeCallbacksAndMessages(null);
ANRSharedPrefs.storeANR(context, true, SystemClock.elapsedRealtime());
ANRError error = ANRError.NewMainOnly();
Log.e("WatchDog", "" + error);
Log.d("WatchDog", "Now restarting the app");
RestartAppUtil.restartApp(context);
return;
}
}
}
}
Here is how the watchdog is started
public class FileLogger extends Application {
ANRWatchDog watchDog = new ANRWatchDog(this);
/**
* Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
*/
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Now launching Android Application : " + BuildConfig.VERSION_NAME);
File logFile = new File(ExternalStoragePath.getExternalCardPath(getApplicationContext()), "log.txt");
try {
String cmd = "logcat -v time -f " + logFile.getPath() + " TAG1:I TAG2:D TAG3:E *:S";
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
Log.e(TAG, "Exception during writing to log " + e);
}
watchDog.start();
}
}
Here is how I am restarting the app i.e RestartUtil
public static void restartApp(Context context){
context.stopService(new Intent(context, Service.class));
Intent mStartActivity = new Intent(context, MainActivity.class);
mStartActivity.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mStartActivity.putExtra(KeyConstants.ANR, true);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
Runtime.getRuntime().exit(0);
}
This code works and the app is restarted.
I am simulating an ANR in one of the activities using an infinite while loop. When I do that, this is what happens in the logs
10-17 13:30:08.221 19588-19608/com.company.project D/TAG1 Count hasn't incremented. This means ANR. Will restart the app. Thread Id : 0
10-17 13:30:08.221 19588-19608/com.company.project D/TAG1 Storing the ANR time : 617417608
10-17 13:30:08.231 19588-19608/com.company.project D/TAG1 Now restarting the app
10-17 13:30:18.411 20333-20353/com.company.project D/TAG1 Count hasn't incremented. This means ANR. Will restart the app. Thread Id : 0
10-17 13:30:18.411 20333-20353/com.company.project D/TAG1 Storing the ANR time : 617427797
10-17 13:30:18.421 20333-20353/com.company.project D/TAG1 Now restarting the app
10-17 13:30:18.791 20362-20362/? D/TAG1: Getting the value of ANR time 617427797
10-17 13:30:18.791 20362-20362/? D/TAG1: Received intent in main screen
10-17 13:30:20.171 20362-20362/com.company.project D/TAG1 Getting the value of ANR time
10-17 13:30:20.171 20362-20362/com.company.project D/TAG1 Received intent in main screen 617427797
The main activity receives two intents, instead of one. Also i don't understand the presence of
/? D/TAG1
in the logs
Can anyone help me in figuring out, why the main screen gets two intents?
So I was finally able to solve this.
System.exit() was not enough in my case. I had to call finish() or finishAffinity() on the activity which was causing the ANR.
So in the onCreate()
method of every activty, I register the instance of activity in the FileLogger like this
FileLogger.setActivityName(this);
This is how the FileLogger has been modified
/**to register the activity)
public static void setActivityName(Activity activityName){
anrActivity = activityName;
}
/**This method is called by RestartUtil method to restart the app**/
public static void kill(){
if ( anrActivity != null) {
anrActivity.finish();
anrActivity.finishAffinity();
}
android.os.Process.killProcess(android.os.Process.myPid());
}
I'm doing a Foreground service in my application, and when I'm calling the method Stopself inside the service it is calling my OnDestroy method but it's not killing my service. It still using memory, I check it through adb shell dumpsys meminfo.
I tried to call StopService too from my application but it's not working. I read a lot of posts from other people with the same problem, but they are using Handlers inside the Service. In my case I manage everything with a Singleton ThreadPool manager, that I already close with shutdown() method when app is closed.
It just happened when I close the app and my service still working. For example:
If I record a Fastmotion video and I wait until it is process, and later, I close my app. I don't have this memory lead. But, if I close the app then the service is processing this, It finish the processing, but I have a memory lead because Server is not killed.
So, hope that someone can see where it fails or what can I change to make this work. Here is my Service code:
/*
Base Service is a abstract class which implement the concurrent methods for the different services of the app
*/
public abstract class BaseService extends Service {
private static final String TAG = "BaseService";
private static final int NOTIFICATION_ID = 10;
private Notification mNotification;
private boolean mIsNotificationShow = false;
/**
* mIsRegistered boolean controls when the application is in background or not.
* Is set to true in {#link #ServiceConnection method}
* Is set to false in {#link #unbindMediaSaveService()}
*/
protected boolean mIsRegistered = false;
/**
* Count the number of request in the service to show the notification
* and hide it when all of them are over
*/
protected int mNotificationCount = 0;
protected synchronized void showNotification() {
mNotificationCount++;
// Notification already shown.
if (mIsNotificationShow)
return;
if (mNotification == null) {
Bitmap bigIcon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
mNotification = new Notification.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText(getResources().getString(R.string.string_processing_notification_service))
.setSmallIcon(R.drawable.ic_menu_savephoto)
.setLargeIcon(bigIcon).build();
}
startForeground(NOTIFICATION_ID, mNotification);
mIsNotificationShow = true;
}
protected synchronized void hideNotification() {
mNotificationCount--;
// Notification already hidden.
if (!mIsNotificationShow)
return;
if (mNotificationCount == 0) {
stopForeground(true);
mIsNotificationShow = false;
tryToCloseService();
}
}
/**
* Set IsRegistered boolean to true or false to check in the service when the application is in background or not
*
* #param register set the boolean value
*/
public void registerServiceClient(boolean register) {
mIsRegistered = register;
Log.i(TAG, "[registerServiceClient] Client registered: " + register);
if (!register) {
tryToCloseService();
}
}
/**
* Try to close the current service. It will be close if the application is in background{#link #mIsRegistered}
* and the service don't have current actions{#link #mNotificationCount}
*/
public void tryToCloseService() {
Log.i(TAG, "[tryToCloseService] Trying to close Service");
if (!mIsRegistered && mNotificationCount == 0) {
Log.i(TAG, "[tryToCloseService] Service stopped");
stopSelf();
} else {
Log.i(TAG, "[tryToCloseService] pending actions " + mNotificationCount);
}
}
}
I initialize a ServiceConnection and bind the service in my activity:
private ServiceConnection mMediaSaveConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder b) {
mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
m
MediaSaveService.registerServiceClient(true);
}
#Override
public void onServiceDisconnected(ComponentName className) {
if (mMediaSaveService != null) {
mMediaSaveService.setListener(null);
mMediaSaveService.setPhotoListener(null);
mMediaSaveService = null;
}
}
};
private void bindMediaSaveService() {
Intent intent = new Intent(this, MediaSaveService.class);
startService(intent);
if (mMediaSaveConnection != null) {
bindService(intent, mMediaSaveConnection, Context.BIND_AUTO_CREATE);
mMediaSaverIsBind = true;
}
}
private void unbindMediaSaveService() {
if (mMediaSaveService != null) {
mMediaSaveService.registerServiceClient(false);
}
if (mMediaSaveConnection != null && mMediaSaverIsBind) {
unbindService(mMediaSaveConnection);
mMediaSaverIsBind = false;
}
}
Finally I call this methods in my onStart / onStop of my activity. Also, if it can help, in the services where I extend my BaseService, I put a START_NOT_STICKY flag to don't recreate the service when it's killed.
I have followed the guide on how to setup google+ sign in. I did every step and basically copy and pasted the code.
Here is the scenario. I develop on two different computers. I have two different client-ids in my console. One for computer A and one for computer B.
When i install the application and launch it, it will attempt to sign in and fail with the following error from logcat. If i back out of the app and re-launch, it will then sign in fine. When it fails, it will seem to be trying to launch an Activity but the Activity is never launched. Here is the logcat.
06-04 10:14:57.801 19948-19948/carbon.android.game.legions D/AccountFragment﹕ ResolveSignInError ErrorCode:4
06-04 10:14:57.801 602-823/? I/ActivityManager﹕ START u0 {cmp=com.google.android.gms/.plus.activity.AccountSignUpActivity (has extras)} from pid -1
06-04 10:14:57.811 178-646/? D/audio_hw_primary﹕ select_devices: out_snd_device(2: speaker) in_snd_device(0: )
06-04 10:14:57.811 178-646/? D/ACDB-LOADER﹕ ACDB -> send_afe_cal
06-04 10:14:57.821 602-2816/? I/ActivityManager﹕ START u0 {act=com.google.android.gms.common.account.CHOOSE_ACCOUNT pkg=com.google.android.gms cmp=com.google.android.gms/.common.account.AccountPickerActivity (has extras)} from pid 20027
06-04 10:14:57.941 20027-20031/? D/dalvikvm﹕ GC_CONCURRENT freed 601K, 7% free 9304K/9940K, paused 2ms+2ms, total 19ms
06-04 10:14:58.071 949-959/? W/GLSUser﹕ GoogleAccountDataService.getToken()
What am i doing wrong? I followed the guide word for word and basically copy and pasted the code. The only difference is that i am inside of a Fragment and not an Activity. But, that shouldn't matter.
Here is the code:
public class AccountFragment extends Fragment implements View.OnClickListener,
ConnectionCallbacks,
OnConnectionFailedListener {
private static final int RC_SIGN_IN = 1524;
private GoogleApiClient googleApiClient;
private boolean intentInProgress;
private boolean signInClicked;
private ConnectionResult connectionResult;
private SignInButton signInButton;
public AccountFragment() {}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "The connection failed: " + connectionResult.getErrorCode());
if (!this.intentInProgress) {
this.connectionResult = connectionResult;
if (this.signInClicked) {
this.resolveSignInError();
}
}
}
#Override
public void onStart() {
super.onStart();
this.googleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
if (this.googleApiClient.isConnected()) {
this.googleApiClient.disconnect();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.googleApiClient = new GoogleApiClient.Builder(this.getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_PROFILE)
.build();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.sign_in_button:
if (!this.googleApiClient.isConnecting() && !this.googleApiClient.isConnected()) {
this.signInClicked = true;
this.resolveSignInError();
} else {
Log.d(TAG, "OnClick else");
}
break;
default:
break;
}
}
#Override
public void onConnected(Bundle bundle) {
this.signInClicked = false;
Person currentPerson = Plus.PeopleApi.getCurrentPerson(this.googleApiClient);
Log.d(TAG, "User connected: " + currentPerson.getDisplayName());
Log.d(TAG, "User id: " + currentPerson.getId());
Toast.makeText(this.getActivity(), "User connected: " + currentPerson.getDisplayName(), Toast.LENGTH_SHORT).show();
}
#Override
public void onConnectionSuspended(int i) {
this.googleApiClient.connect();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RC_SIGN_IN) {
if (resultCode != Activity.RESULT_OK) {
this.signInClicked = false;
}
this.intentInProgress = false;
if (!this.googleApiClient.isConnecting()) {
this.googleApiClient.connect();
}
}
}
private void resolveSignInError() {
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this.getActivity()) != ConnectionResult.SUCCESS) {
Log.e(TAG, "Google Play Services is not available.");
}
Log.d(TAG, "ResolveSignInError ErrorCode:" + this.connectionResult.getErrorCode());
if (this.connectionResult.hasResolution()) {
this.intentInProgress = true;
try {
this.connectionResult.startResolutionForResult(this.getActivity(), RC_SIGN_IN);
} catch (SendIntentException e) {
e.printStackTrace();
this.intentInProgress = false;
this.googleApiClient.connect();
}
}
}
}
I figured out my issue.
There were a couple of issues.
With all my testing, i have been attempting to sign in the whole time. And was successful sometimes. Somehow, i was remaining authenticated even though my app was not signed in. I added the ability to sign out and revoke access. After revoking access and attempting to sign in again, the Activity would launch to resolve any errors.
I was also having the issue that is being discussed here. My host Activity was consuming my onActivityResult(...) from my connectionResult.startResolutionForResult(...);. So, after some trial and error i finally found a solution to that issue as well. The question linked helped but did not fully solve the issue. Please view my answer to that question for how i solved the problem.
Lesson, make sure that you are signing out and revoking access while testing. If you are having these issues, try revoking access and then signing back in.
In my case i solve my problem by doing following step, its old que but others my also having this problem so
Follow these stem in android development Console
Open the Credentials page.
Click Add credentials > OAuth 2.0 client ID.
Select Android.
and fill the fingerprint and package name .
Click Create.
Then there will be successful sing in from google.
Hope this may solve your problem. !!!
Please msg me if any problem occurs.
I just set up GCM in my Android App. But I have the problem that I don't know how to check if the device is already registered. I work with the new google play services library.
The register part looks like this:
#Override
protected String doInBackground(String... arg0) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context_app);
}
regid = gcm.register(SENDER_ID);
msg = "Dvice registered, registration ID=" + regid;
Log.d("111", msg);
sendRegistrationIdToBackend(regid);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
}
return msg;
}
How can I modify this that it checks if the device is already registered?
Store the registration id in a databade table or shared preference and when app starting..check whether it is null or not
Google has provided very clear documentation with code.You should use following code:
// Make sure the device has the proper dependencies.
GCMRegistrar.checkDevice(this);
// Make sure the manifest was properly set - comment out this line
// while developing the app, then uncomment it when it's ready.
GCMRegistrar.checkManifest(this);
registerReceiver(mHandleMessageReceiver,
new IntentFilter(DISPLAY_MESSAGE_ACTION));
final String regId = GCMRegistrar.getRegistrationId(this);
if (regId.equals("")) {
// Automatically registers application on startup.
GCMRegistrar.register(this, SENDER_ID);
} else {
// Device is already registered on GCM, check server.
if (GCMRegistrar.isRegisteredOnServer(this)) {
// Skips registration.
mDisplay.append(getString(R.string.already_registered) + "\n");
} else {
// Try to register again, but not in the UI thread.
// It's also necessary to cancel the thread onDestroy(),
// hence the use of AsyncTask instead of a raw thread.
final Context context = this;
mRegisterTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
boolean registered =
ServerUtilities.register(context, regId);
// At this point all attempts to register with the app
// server failed, so we need to unregister the device
// from GCM - the app will try to register again when
// it is restarted. Note that GCM will send an
// unregistered callback upon completion, but
// GCMIntentService.onUnregistered() will ignore it.
if (!registered) {
GCMRegistrar.unregister(context);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mRegisterTask = null;
}
};
mRegisterTask.execute(null, null, null);
}
}
#Override
protected void onDestroy() {
if (mRegisterTask != null) {
mRegisterTask.cancel(true);
}
unregisterReceiver(mHandleMessageReceiver);
GCMRegistrar.onDestroy(this);
super.onDestroy();
}
private final BroadcastReceiver mHandleMessageReceiver =
new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
mDisplay.append(newMessage + "\n");
}
};
when you get registration Id, Store it in SharedPreferences, for example:
SharedPreferences shp = context.getSharedPreferences("anyNameYouLike",MODE_PRIVATE);
SharedPreferences.Editor editor=shp.edit();
editor.putString("RegID",registrationID).commit;
In the next time before you register check the "anyNameYouLike" if it contain field called RegID Like this:
private boolean isRegistered(Context context){
SharedPreferences shp = context.getSharedPreferences("anyNameYouLike",PRIVATE_MODE);
return shp.contains("RegID");
}