i have one login activity in which i am login using google. after successfully login i am moving to main screen. which has navigation drawer. now from the list of fragments, i want to sign out from google using one of fragment. how can i achieve this. below is my code:
LoginActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Session Manager
session = new SessionManager(getApplicationContext());
initUi();
setupListeners();
}
protected void onStart() {
super.onStart();
}
protected void onStop() {
super.onStop();
if (MyApplication.mGoogleApiClient.isConnected()) {
MyApplication.mGoogleApiClient.disconnect();
}
}
private void initUi(){
llGoogle = (LinearLayout)findViewById(R.id.activity_login_llsignin_google);
}
private void setupListeners(){
llGoogle.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (session.isConnected()) {
getProfileInformation();
} else {
}
}
});
}
private void resolveSignInError() {
if (MyApplication.mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
MyApplication.mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
} catch (SendIntentException e) {
mIntentInProgress = false;
MyApplication.mGoogleApiClient.connect();
}
}
}
private void googlePlusLogin() {
MyApplication.googlePlusLogin();
resolveSignInError();
}
MyApplication.java
public class MyApplication extends Application implements
ConnectionCallbacks, OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult>{
public static Typeface app_medium;
public static Typeface app_regular;
public static Typeface app_bold;
public static final String TAG = MyApplication.class.getSimpleName();
private static SharedPreferences Pref;
private static MyApplication mInstance;
private static final int RC_SIGN_IN = 0;
// Google client to communicate with Google
public static GoogleApiClient mGoogleApiClient;
public boolean mIntentInProgress;
public static boolean signedInUser;
public static ConnectionResult mConnectionResult;
#SuppressWarnings("unused")
public void onCreate() {
super.onCreate();
mInstance = this;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
Pref = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
checkFBKey();
app_regular = Typeface.createFromAsset(getAssets(),
"fonts/dax_regular.ttf");
app_medium = Typeface.createFromAsset(getAssets(),
"fonts/dax_medium.ttf");
app_bold = Typeface.createFromAsset(getAssets(),
"fonts/dax_bold.ttf");
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
/**
* set user login
* */
// public static void setUserFBLogin() {
// // TODO Auto-generated method stub
// Editor edit_login_detail = Pref.edit();
// edit_login_detail.putBoolean(GeneralClass.temp_iUserFaceBookBLOGIN,
// true);
// edit_login_detail.commit();
// }
public void checkFBKey() {
PackageInfo info;
try {
info = getPackageManager().getPackageInfo(getPackageName(),
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md;
md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
String something = new String(Base64.encode(md.digest(), 0));
// String something = new
// String(Base64.encodeBytes(md.digest()));
Log.e("hash key", something);
}
} catch (NameNotFoundException e1) {
Log.e("name not found", e1.toString());
} catch (NoSuchAlgorithmException e) {
Log.e("no such an algorithm", e.toString());
} catch (Exception e) {
Log.e("exception", e.toString());
}
}
public static void googlePlusLogin() {
if (!mGoogleApiClient.isConnecting()) {
signedInUser = true;
}
}
public static void googlePlusLogout() {
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
// updateProfile(false);
}
}
public static void revokeGplusAccess() {
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(mGoogleApiClient)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status arg0) {
Log.e("LOGIN", "User access revoked!");
mGoogleApiClient.connect();
}
});
}
}
#Override
public void onLowMemory() {
// TODO Auto-generated method stub
super.onLowMemory();
}
#Override
public void onResult(LoadPeopleResult arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
if (!arg0.hasResolution()) {
return;
}
if (!mIntentInProgress) {
// store mConnectionResult
MyApplication.mConnectionResult = arg0;
if (signedInUser) {
}
}
}
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
Log.e("APPLICATION", "CONNECTED");
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
mGoogleApiClient.connect();
}
}
Now, i want to use googlePlusLogout() method in my fragment. how can i do that.?
You should implement all your global credential and methods in Application class so you call it from any Activity or Fragment class.
Declare Set your LoginActivity as CurrentActivity in Application class and using instanceOf call loginSuccessful method of LoginActivity from Application at onConnected() method. and you can call logOut method from Fragment of an Application class.
Check Follow Example.
/**
* #author AA-Sk
*
*/
public class MyApplication extends Application {
private Activity mCurrentActivity;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onConnected(Bundle mBundle) {
Activity mActivity = getmCurrentActivity();
if (mActivity != null) {
if (mActivity instanceof LoginActivity) {
LoginActivity mLoginActivity = (LoginActivity) mActivity;
mLoginActivity.loginSuccessfull(mBundle);
}
}
}
private void googleLogout() {
}
public void setmCurrentActivity(Activity mCurrentActivity) {
this.mCurrentActivity = mCurrentActivity;
}
public Activity getmCurrentActivity() {
return mCurrentActivity;
}
/**
* #author AA-Sk
*
*/
public class LoginActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((MyApplication) getApplication()).setmCurrentActivity(LoginActivity.this);
}
private void loginSuccessfull(Bundle mBundle) {
// Store Data from bundle and call another activity as user is successfully logged in.
}
}
/**
* #author AA-Sk
*
*/
public class SampleActivity extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
/**
* #author AA-Sk
*
*/
public class logout extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
public logout() {
((MyApplication) getActivity().getApplication()).googleLogout();
}
}
}
Related
I have a class that extends Activity, When I try to access the context from the onCreate() method it gets printed but when I save it in a variable context and try to access it from the committext() function as shown below, It prints null. I also tried using "this" and getBaseContext() directly from the committext() function as it is a part of the same class, I get null pointer exception. Please help me figure out what is going wrong.
public class MainKeyboardActionListener extends Activity implements KeyboardView.OnKeyboardActionListener, View.OnTouchListener {
private Context context;
public static boolean active = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mode_keyboard, false);
context=getBaseContext();
System.out.println("contexxtt1"+context);
}
#Override
public void onStart() {
super.onStart();
active = true;
}
#Override
protected void onResume() {
super.onResume();
}
private static class myHandler extends Handler {
}
;
public void setInputConnection(InputConnection ic) {
}
#Override
public void onKey(int arg0, int[] arg1) {
// TODO Auto-generated method stub
}
#Override
public void onPress(int keyCode) {
}
#Override
public void onRelease(int keyCode) {
commitText(String.valueOf(keyCode));
}
private void handleException(int keyCode) {
}
private void removeHalantMode() {
}
private void commitText(String text) {
if(active==true) {
System.out.println("contexxtt"+context);
}
}
#Override
public void onText(CharSequence arg0) {
// TODO Auto-generated method stub
}
#Override
public void swipeDown() {
// TODO Auto-generated method stub
}
#Override
public void swipeLeft() {
// TODO Auto-generated method stub
}
#Override
public void swipeRight() {
// TODO Auto-generated method stub
}
#Override
public void swipeUp() {
// TODO Auto-generated method stub
}
#Override
protected void onPause() {
super.onPause();
}
#Override
public void onStop() {
super.onStop();
active = false;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Make your myHandler class not static.
Im running into a problem when trying to submit a score to my Play Services Leader board. From my MainActivity the user is logged in successfully then from my GameScreen activity I try to submit a score but it fails:(...My Question is does the connection persist or do I have to reconnect the user before I submit???
MAIN ACTIVITY.
public class MainActivity extends BaseGameActivity implements View.OnClickListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
Button siButton;
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.build();
siButton = (Button) findViewById(R.id.sign_out_button);
siButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (view.getId() == R.id.sign_in_button) {
beginUserInitiatedSignIn();
} else if (view.getId() == R.id.sign_out_button) {
signOut();
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_button).setVisibility(View.GONE);
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onSignInSucceeded() {
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_button).setVisibility(View.VISIBLE);
}
#Override
public void onSignInFailed() {
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_button).setVisibility(View.GONE);
}
#Override
public void onClick(View v) {
}
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
GAMESCREEN
public class GameScreen extends BaseGameActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private int c;
private GoogleApiClient mGoogleApiClient;
TextView counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_screen);
setRequestedClients(BaseGameActivity.CLIENT_GAMES | BaseGameActivity.CLIENT_APPSTATE);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.build();
private void progressSetup() {
Thread timerThread = new
Thread() {
#Override
public void run() {
try {
while (mbActive && (waited < TIMER_RUNTIME)) {
sleep(THREAD_SLEEP);
if (mbActive) {
waited += 100;
updateProgress(waited);
if (waited > 9999) {
mbActive = false;
gameOver();
}
}
}
} catch (InterruptedException e) {
Log.d("fail", "failure" + e);
}
}
};
startTread = false;
timerThread.start();
}
private void updateProgress(final int timePassed) {
if (null != mProgressBar) {
progress = mProgressBar.getMax() * timePassed / TIMER_RUNTIME;
mProgressBar.setProgress(progress);
}
}
//game over
private void gameOver() {
runOnUiThread(new Runnable() {
#Override
public void run() {
upDateScore();
}
});
}
private void upDateScore(){
if (mGoogleApiClient.isConnected()) {
Games.Leaderboards.submitScore(mGoogleApiClient, getString(R.string.app_id), c);
Log.d("connectted.....................................................");
} else {
Log.d("not connectted.....................................................");
}
}
#Override
public void onBackPressed() {
Intent home = new Intent(GameScreen.this, MainActivity.class);
home.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(home);
}
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
#Override
public void onSignInFailed() {
}
#Override
public void onSignInSucceeded() {
}
}
Just replace getString(R.string.app_id) with your LEADERBOARD id in method Games.Leaderboards.submitScore(mGoogleApiClient, getString(R.string.app_id).
Leaderboard id looks like this: "CgkI0tXt-q0HEA****"
Ivan Syabro is right. You must use the LEADERBOARD_ID, see Leaderboards in Android - Updating the player's score.
In the developer console's game services section, you can easily export your leaderboard and achievements ids as xml files using the provided button.
In general, using the game services with more than one activity might cause additional waiting periods as each of them signs in individually at its start. Therefore, as far as I know, the implementation with fragments should be preferred, see this famous example playgameservices/android-basic-samples.
I have a trouble with getting Activity(Nullpointerexception) after that I have rotate screen and received callback from AsyncTask to update my views of the fragment. If I wont change orientation then everything is OK(but not all the time, sometimes this bug appears)
My main activity:
public class MainActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager_layout);
fm = getSupportFragmentManager();
fm.addOnBackStackChangedListener(this);
session = new SessionManager(getApplicationContext());
if (session.isAuthorizated()) {
disableTabs();
FragmentTransaction ft = fm.beginTransaction();
if (session.termsAndConditions()) {
ft.replace(android.R.id.content, new TermsAndConditionsFragment(), "terms-and-conditions").commit();
}
}
} else {
enableTabs();
mTabsAdapter = new TabsAdapter(this, mViewPager);
mTabsAdapter.addTab(actionBar.newTab().setText("Log in"), LoginFragment.class, null);
mTabsAdapter.addTab(actionBar.newTab().setText("Calculator"), CalculatorFragment.class, null);
}
}
That`s my fragment:
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnEditorActionListener, ValueSelectedListener, AsyncUpdateViewsListener {
private static final String TAG = "TermsAndConditionsFragment";
private TermsAndConditionsManager termsAndConditionsM;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prepareData();
}
public void prepareData() {
if (getSherlockActivity() == null)
Log.d(TAG, "Activity is null");
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity().getApplicationContext());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
...
// some stuff
...
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
//bla bla bla
return rootView;
}
public void updateTermsAndConditionsView() {
//update views here
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
switch (v.getId()) {
case R.id.etHowMuch:
d = NumberPaymentsPickerFragment.newInstance(getSherlockActivity(), Integer.valueOf(howMuch.replace("£", "")), 0);
d.setValueSelectedListener(this);
d.show(getFragmentManager(), Const.HOW_MUCH);
break;
}
}
#Override
public void onValueSelected() {
Bundle args = new Bundle();
...
ExecuteServerTaskBackground task = new ExecuteServerTaskBackground(getSherlockActivity());
task.setAsyncUpdateViewsListener(this);
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
task.args = args;
task.execute();
}
#Override
public void onUpdateViews() {
prepareData();
updateTermsAndConditionsView();
}
}
My AsyncTask with callback:
public class ExecuteServerTaskBackground extends AsyncTask<Void, Void, Void> {
private static final String TAG = "ExecuteServerTaskBackground";
Activity mActivity;
Context mContext;
private AsyncUpdateViewsListener callback;
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
public void setAsyncUpdateViewsListener(AsyncUpdateViewsListener listener) {
callback = listener;
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
msg = server.serverRequest(action, args);
else
msg = server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
callback.onUpdateViews();
}
}
Why does it behave so? How can I get activity correctly if I change orientation.
EDIT:
As I understand correctly nullpointer appears after orientation changed and asynctask executed due to wrong reference between asyctask and Activity. Recreated activity doesnt have this reference thats why when I receive callback I use wrong activity reference which isn`t exist anymore. But how can I save current activity reference?
EDIT:
I have decided to try realize my task throughout Service and that`s what I have done.
Activity:
public class MainFragment extends Fragment implements ServiceExecutorListener, OnClickListener {
private static final String TAG = MainFragment.class.getName();
Button btnSend, btnCheck;
TextView serviceStatus;
Intent intent;
Boolean bound = false;
ServiceConnection sConn;
RESTService service;
ProgressDialog pd = new ProgressDialog();
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
intent = new Intent(getActivity(), RESTService.class);
getActivity().startService(intent);
sConn = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder binder) {
Log.d(TAG, "MainFragment onServiceConnected");
service = ((RESTService.MyBinder) binder).getService();
service.registerListener(MainFragment.this);
if (service.taskIsDone())
serviceStatus.setText(service.getResult());
bound = true;
}
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "MainFragment onServiceDisconnected");
bound = false;
}
};
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main_fragment, container, false);
serviceStatus = (TextView) rootView.findViewById(R.id.tvServiceStatusValue);
btnSend = (Button) rootView.findViewById(R.id.btnSend);
btnCheck = (Button) rootView.findViewById(R.id.btnCheck);
btnSend.setOnClickListener(this);
btnCheck.setOnClickListener(this);
return rootView;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSend:
pd.show(getFragmentManager(), "ProgressDialog");
service.run(7);
service.run(2);
service.run(4);
break;
case R.id.btnCheck:
if (service != null)
serviceStatus.setText(String.valueOf(service.taskIsDone()) + service.getTasksCount());
break;
}
}
#Override
public void onStart() {
super.onStart();
Log.d(TAG, "Bind service");
getActivity().bindService(intent, sConn, 0);
}
#Override
public void onPause() {
super.onDestroy();
Log.d(TAG, "onDestroy: Unbind service");
if (!bound)
return;
getActivity().unbindService(sConn);
service.unregisterListener(this);
bound = false;
}
#Override
public void onComplete(String result) {
Log.d(TAG, "Task Completed");
pd.dismiss();
serviceStatus.setText(result);
}
}
Dialog:
public class ProgressDialog extends DialogFragment implements OnClickListener {
final String TAG = ProgressDialog.class.getName();
public Dialog onCreateDialog(Bundle savedInstanceState) {
setRetainInstance(true);
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity())
.setTitle("Title!")
.setPositiveButton(R.string.yes, this)
.setNegativeButton(R.string.no, this)
.setNeutralButton(R.string.maybe, this)
.setCancelable(false)
.setMessage(R.string.message_text)
.setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
return true;
}
});
return adb.create();
}
public void onClick(DialogInterface dialog, int which) {
int i = 0;
switch (which) {
case Dialog.BUTTON_POSITIVE:
i = R.string.yes;
break;
case Dialog.BUTTON_NEGATIVE:
i = R.string.no;
break;
case Dialog.BUTTON_NEUTRAL:
i = R.string.maybe;
break;
}
if (i > 0)
Log.d(TAG, "Dialog 2: " + getResources().getString(i));
}
public void onDismiss(DialogInterface dialog) {
Log.d(TAG, "Dialog 2: onDismiss");
// Fix to avoid simple dialog dismiss in orientation change
if ((getDialog() != null) && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
Log.d(TAG, "Dialog 2: onCancel");
}
}
Service:
public class RESTService extends Service {
final String TAG = RESTService.class.getName();
MyBinder binder = new MyBinder();
ArrayList<ServiceExecutorListener> listeners = new ArrayList<ServiceExecutorListener>();
Handler h = new Handler();
RequestManager mRequest;
ExecutorService es;
Object obj;
int time;
StringBuilder builder;
String result = null;
public void onCreate() {
super.onCreate();
Log.d(TAG, "RESTService onCreate");
es = Executors.newFixedThreadPool(1);
obj = new Object();
builder = new StringBuilder();
}
public void run(int time) {
RunRequest rr = new RunRequest(time);
es.execute(rr);
}
class RunRequest implements Runnable {
int time;
public RunRequest(int time) {
this.time = time;
Log.d(TAG, "RunRequest create");
}
public void run() {
Log.d(TAG, "RunRequest start, time = " + time);
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Log.d(TAG, "RunRequest obj = " + obj.getClass());
} catch (NullPointerException e) {
Log.d(TAG, "RunRequest error, null pointer");
}
builder.append("result " + time + ", ");
result = builder.toString();
sendCallback();
}
}
private void sendCallback() {
h.post(new Runnable() {
#Override
public void run() {
for (ServiceExecutorListener listener : listeners)
listener.onComplete();
}
});
}
public boolean taskIsDone() {
if (result != null)
return true;
return false;
}
public String getResult() {
return result;
}
public void registerListener(ServiceExecutorListener listener) {
listeners.add(listener);
}
public void unregisterListener(ServiceExecutorListener listener) {
listeners.remove(listener);
}
public IBinder onBind(Intent intent) {
Log.d(TAG, "RESTService onBind");
return binder;
}
public boolean onUnbind(Intent intent) {
Log.d(TAG, "RESTService onUnbind");
return true;
}
public class MyBinder extends Binder {
public RESTService getService() {
return RESTService.this;
}
}
}
As you mention in your edit, the current Activity is destroyed and recreated on orientation change.
But how can I save current activity reference?
You shouldn't. The previous Activity is no longer valid. This will not only cause NPEs but also memory leaks because the AsyncTask might hold the reference to old Activity, maybe forever.
Solution is to use Loaders.
I have started using the Google+ API for android, and I have created a sign-in application following this tutorial:
https://developers.google.com/+/mobile/android/sign-in
Now, the problem is that I want to create the sign out button from a different Activity, and what i tried to do didn't really worked..
My GPlusLogin code (Activity for the Google+ Login):
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import com.google.android.gms.common.*;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.plus.PlusClient;
public class GPlusLogin extends Activity implements ConnectionCallbacks, OnConnectionFailedListener{
private static final int REQUEST_CODE_RESOLVE_ERR = 9000;
private static final String TAG = "GPlusLogin";
private ProgressDialog mConnectionProgressDialog;
private PlusClient mPlusClient;
private ConnectionResult mConnectionResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.gplus_layout);
mPlusClient = new PlusClient.Builder(this, this, this).setVisibleActivities("http://schemas.google.com/AddActivity", "http://schemas.google.com/BuyActivity").build();
Bundle extras = getIntent().getExtras();
mConnectionProgressDialog = new ProgressDialog(this);
mConnectionProgressDialog.setMessage("Signing in...");
if(extras!=null){
if(extras.getString("signout")!=null){
if (mPlusClient.isConnected()) {
mPlusClient.clearDefaultAccount();
mPlusClient.disconnect();
mPlusClient.connect();
finish();
startActivity(getIntent());
}
}
}else{
findViewById(R.id.sign_in_button).setOnClickListener(new OnClickListener() {
public void onClick(View view) {
// TODO Auto-generated method stub
if (view.getId() == R.id.sign_in_button && !mPlusClient.isConnected()) {
if (mConnectionResult == null) {
mConnectionProgressDialog.show();
} else {
try {
mConnectionResult.startResolutionForResult(GPlusLogin.this, REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
// Try connecting again.
mConnectionResult = null;
mPlusClient.connect();
}
}
}
}
});
}
}
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
mPlusClient.connect();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
mPlusClient.disconnect();
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// TODO Auto-generated method stub
if (mConnectionProgressDialog.isShowing()) {
// The user clicked the sign-in button already. Start to resolve
// connection errors. Wait until onConnected() to dismiss the
// connection dialog.
if (result.hasResolution()) {
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
mPlusClient.connect();
}
}
}
mConnectionResult = result;
}
#Override
protected void onActivityResult(int requestCode, int responseCode, Intent intent) {
if (requestCode == REQUEST_CODE_RESOLVE_ERR && responseCode == RESULT_OK) {
mConnectionResult = null;
mPlusClient.connect();
}
}
#Override
public void onConnected() {
// TODO Auto-generated method stub
mConnectionProgressDialog.dismiss();
Intent main = new Intent(GPlusLogin.this, MainActivity.class);
main.putExtra("result", true);
startActivity(main);
}
#Override
public void onDisconnected() {
// TODO Auto-generated method stub
Log.d(TAG, "disconnected");
}
}
My Disconnect code on MainActivity:
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bundle extras = getIntent().getExtras();
if(extras==null){
Intent intent = new Intent(this, GPlusLogin.class);
startActivity(intent);
}
TextView text1 = (TextView) findViewById(R.id.text1);
text1.setText("You Are Connected :D");
Button SignOut = (Button) findViewById(R.id.sign_out_gplus);
SignOut.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this, GPlusLogin.class);
intent.putExtra("signout", true);
startActivity(intent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Just add this on your new activity, where you want your logout-button for google+ to be there :
#Override
protected void onStart() {
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
mGoogleApiClient.connect();
super.onStart();
}
and next:
signout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// ...
Toast.makeText(getApplicationContext(),"Logged Out",Toast.LENGTH_SHORT).show();
Intent i=new Intent(getApplicationContext(),MainActivity.class);
startActivity(i);
}
});
}
});
Hey i solved this problem by myself, working like charm
What is the problem : Google plus signIn in one activity but need to Logout from another activity
Solution:
My Google-plus Logout Activity is like this:
public class MainActivity extends Activity implements OnClickListener,
ConnectionCallbacks, OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult> {
GoogleApiClient mGoogleApiClient;
boolean mSignInClicked;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
//copy this code on "Logout" Onclick
logout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
// updateUI(false);
System.err.println("LOG OUT ^^^^^^^^^^^^^^^^^^^^ SUCESS");
}
}
});
}
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
mSignInClicked = false;
// updateUI(true);
Plus.PeopleApi.loadVisible(mGoogleApiClient, null).setResultCallback(
this);
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
mGoogleApiClient.connect();
// updateUI(false);
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
public void onResult(LoadPeopleResult arg0) {
// TODO Auto-generated method stub
}
Description about solution:
For single package google plus API will generate one token & session.Just here simply make one more session in logout page also.You can easily logout from session now
I to have tried a lot about this problem,to logout from current session, just try this .it will definitely work. any doubts let me know
It would probably be easier to create a base class and inherit the connect/disconnect methods. Photohunt, our full sample, documents this design in detail.
Docs
Code
You can get instance of FirebaseAuth anywhere from the app as FirebaseAuth is a singleton class.
mAuth = FirebaseAuth.getInstance();
mAuth.signOut();
After struggling for over a week to find out the answer.
I did this,
After signing in save boolean isSignedIn in sharedpreferences as true.
private SharedPreferences.Editor editor;
private SharedPreferences prefs;
editor = getSharedPreferences(getString(R.string.userDetails), MODE_PRIVATE).edit();
editor.putBoolean(getString(R.string.isSignedIn), true);
editor.apply();`
Now from any activity when the user clicks logout, change the boolean to false.
In your Login Activity where googleApiClient is build. In its onStart method.
Check if isSignedIn is false.
#Override
public void onStart() {
super.onStart();
if (!prefs.getBoolean(getString(R.string.isSignedIn), false)) {
signOut();
}
}
Do the same in onConnected
#Override
public void onConnected(Bundle connectionHint) {
if (mGoogleApiClient.isConnected()) {
Log.i(TAG, "onConnected: " + "yes it is connected");
if (!prefs.getBoolean(getString(R.string.isSignedIn), false)) {
signOut();
}
}
}
This will logout and revokeAccess.
public void signOut() {
if (mGoogleApiClient != null) {
Log.e(TAG, "signOut: " + mGoogleApiClient + mGoogleApiClient.isConnected());
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
if (mGoogleApiClient.isConnected()) {
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// ...
Log.i(TAG, "onResult: " + mGoogleApiClient);
}
});
Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
Log.i(TAG, "onResult: Revoke Access status:" + status.getStatus());
}
});
}
}
}
Once you click logout from another activity,try send an intent with extra to indicate that logout button is clicked. Then on Login Activity
if (Intent.Extras != null && Intent.Extras.ContainsKey("LogoutAction")) {
_logoutRequest = Intent.Extras.GetBoolean("LogoutAction");
}
if (_logoutRequest) {
await PlusClass.AccountApi.RevokeAccessAndDisconnect(_apiClient);
_apiClient.Disconnect();
_apiClient.Connect ();
_logoutRequest = false;
}
Other Activity
var intent = new Intent(this.Activity,typeof(LoginActivity));
intent.PutExtra("LogoutAction",true);
Jonathan is correct that a base class or a fragment would make your life easier. That said, the code here could work - the problem is that you're checking whether the PlusClient is connected in onCreate() - but you don't connect it until onStart(). You'd probably need to check the intent in the onConnected() method, and perform the sign out there.
sommesh's answer is perfect, but for less code you can use "Public Static Method" like this:
public static GoogleApiClient mGoogleApiClient;
...
...
public static void signOutFromGoogle() {
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
//...
}
});
}
And on your other Activity call it:
Your_Google_Activity.mGoogleApiClient.connect();
btnSignOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Your_Google_Activity.signOutFromGoogle();
}
});
Here's my solution. I have made a Utils singleton class. In my LoginActivity, I have a GoogleSignInClient object. So just before starting the DashboardActivity after login, I save the instance of googleSignInClient object by calling Utils.getInstance().setGoogleSignInClient(googleSignInClient). Now anywhere else, if I want to logout I have this method in Utils ready:
public void signOut() {
googleSignInClient.signOut();
FirebaseAuth.getInstance().signOut();
}
So now, I can do this from any other activity:
else if (id == R.id.action_logout) {
Utils.getInstance().signOut();
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
}
Yes, you need to log out from both of them, otherwise, you might not see the account chooser the next time you tap the login button.
I have implemented login with facebook in my project.
The code is below:
public class login extends Activity{
ImageView fbtn;
private SharedPreferences mPrefs;
static Facebook facebook = new Facebook("271089732997803");
String access_token;
long expires;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.yf_login1);
mPrefs = getPreferences(MODE_PRIVATE);
access_token = mPrefs.getString("access_token", null);
expires = mPrefs.getLong("access_expires", 0);
fbtn = (ImageView)findViewById(R.id.fbtn);
fbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(access_token != null) {
facebook.setAccessToken(access_token);
Log.v("access_token", access_token);
}
if(expires != 0) {
facebook.setAccessExpires(expires);
Log.i("expires", ""+expires);
}
if (!facebook.isSessionValid()) {
facebook.authorize(login.this,new String[] {}, new DialogListener() {
#Override
public void onComplete(Bundle values) {
SharedPreferences.Editor editor = mPrefs.edit();
editor.putString("access_token", facebook.getAccessToken());
editor.putLong("access_expires", facebook.getAccessExpires());
editor.commit();
}
#Override
public void onFacebookError(FacebookError error) {
}
#Override
public void onError(DialogError e) {
}
#Override
public void onCancel() {
}
});
}
else{
startActivity(new Intent(login.this,ChooseTeam.class));
}
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
facebook.authorizeCallback(requestCode, resultCode, data);
}
#Override
public void onResume() {
super.onResume();
facebook.extendAccessTokenIfNeeded(this, null);
}
Now my question is when i click on the the fb button it will load the progress bar and after 30-40 second it returns the same page.
The most important thing is when i run the same project in my another pc it will run perfectly, opens the dialog of login for the facebook and got the value in my preferences. But in my case i cannot even get the preferences made in my data.
What will be the problem in my emulator?? I am using eclipse galilio and sdk20.
I got the solution actually my antivirus is blocked the internet for the emulator. So i have uninstalled the antivirus and run the app and it works.
Thank you all for helping me out.
Try this....
and use this Permission for Share in Facebook..
private String[] mPermissions={"publish_stream"};
mFb.authorize(SettingActivity.this, mPermissions,new com.fbintegration.Facebook.DialogListener()
{
public void onFacebookError(FacebookError e)
{
}
public void onError(DialogError e)
{
}
public void onComplete(Bundle values)
{
SessionStore.save(mFb, getApplicationContext());
}
public void onCancel()
{
// TODO Auto-generated method stub
}
});
and this is Facebook Connector Class....
public class FacebookConnector
{
private Facebook facebook = null;
private Context context;
private String[] permissions;
private Handler mHandler;
private Activity activity;
//private SessionListener mSessionListener = new SessionListener();;
public FacebookConnector(String appId,Activity activity,Context context,String[] permissions)
{
this.facebook = new Facebook(appId);
SessionStore.restore(facebook, context);
this.context=context;
this.permissions=permissions;
this.mHandler = new Handler();
this.activity=activity;
}
public void login()
{
if (!facebook.isSessionValid())
{
facebook.authorize(this.activity, this.permissions,new LoginDialogListener());
}
}
/*public void logout()
{
SessionEvents.onLogoutBegin();
AsyncFacebookRunner asyncRunner = new AsyncFacebookRunner(this.facebook);
asyncRunner.logout(this.context, new LogoutRequestListener());
}*/
public void postMessageOnWall(String msg)
{
if (facebook.isSessionValid())
{
Bundle parameters = new Bundle();
parameters.putString("message", msg);
try
{
//JSONObject response=Util.parseJson(facebook.request("me/feed", parameters,"POST"));
String response = facebook.request("me/feed", parameters,"POST");
System.out.println(response);
}
catch (IOException e)
{
e.printStackTrace();
}
}
else
{
}
}
private final class LoginDialogListener implements DialogListener
{
public void onComplete(Bundle values)
{
SessionEvents.onLoginSuccess();
}
public void onFacebookError(FacebookError error)
{
SessionEvents.onLoginError(error.getMessage());
}
public void onError(DialogError error)
{
SessionEvents.onLoginError(error.getMessage());
}
public void onCancel()
{
SessionEvents.onLoginError("Action Canceled");
}
}
private class SessionListener implements AuthListener, LogoutListener
{
public void onAuthSucceed()
{
SessionStore.save(facebook, context);
}
public void onAuthFail(String error) {
}
public void onLogoutBegin() {
}
public void onLogoutFinish() {
SessionStore.clear(context);
}
}
public Facebook getFacebook()
{
return this.facebook;
}
}