Google Log in issue - android

Am implementing google sign in my android application,in that i can log in using the google sign in after the success log in ,i want redirect from login page to my homepageactvity.But from the Home page activity i can log out (disconnect Google api client),when clicking the log out button again the Homepageactvity is coming..pls help me to figure this issue. My Login actvity is below
public class LoginActivityGoogle extends Activity implements OnClickListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final int RC_SIGN_IN = 0;
// Google client to communicate with Google
private GoogleApiClient mGoogleApiClient;
private String TAG = "Login";
private boolean mIntentInProgress;
private boolean signedInUser;
private ConnectionResult mConnectionResult;
private SignInButton signinButton;
private ImageView image;
private TextView username, emailLabel;
private LinearLayout profileFrame, signinFrame;
SessionManager session;
private boolean mSignInClicked;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_google);
signinButton = (SignInButton) findViewById(R.id.signin);
signinButton.setOnClickListener(this);
image = (ImageView) findViewById(R.id.image);
username = (TextView) findViewById(R.id.username);
emailLabel = (TextView) findViewById(R.id.email);
profileFrame = (LinearLayout) findViewById(R.id.profileFrame);
signinFrame = (LinearLayout) findViewById(R.id.signinFrame);
session = new SessionManager(getApplicationContext());
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(new Scope(Scopes.PROFILE))
.addScope(new Scope(Scopes.EMAIL))
.build();
}
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
private void resolveSignInError() {
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
} catch (SendIntentException e) {
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, 0).show();
return;
}
if (!mIntentInProgress) {
// store mConnectionResult
mConnectionResult = result;
if (signedInUser) {
resolveSignInError();
}
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
if (requestCode == RC_SIGN_IN) {
// If the error resolution was not successful we should not resolve further.
if (resultCode != RESULT_OK) {
signedInUser = false;
}
signedInUser = false;
mGoogleApiClient.connect();
}
}
#Override
public void onConnected(Bundle arg0) {
signedInUser = false;
Toast.makeText(this, "Connected", Toast.LENGTH_LONG).show();
// To launch from gere to homwpageactivity
Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
String personPhotoUrl = currentPerson.getImage().getUrl();
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
Intent in = new Intent(getApplicationContext(), HomePageActivity.class);
in.putExtra("username",personName);
in.putExtra("email",email);
in.putExtra("profile_pic",personPhotoUrl);
startActivity(in);
getProfileInformation();
}
private void updateProfile(boolean isSignedIn) {
if (isSignedIn) {
signinFrame.setVisibility(View.GONE);
// profileFrame.setVisibility(View.VISIBLE);
} else {
signinFrame.setVisibility(View.VISIBLE);
//profileFrame.setVisibility(View.GONE);
}
}
private void getProfileInformation() {
try {
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
String personPhotoUrl = currentPerson.getImage().getUrl();
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
updateProfile(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onConnectionSuspended(int cause) {
mGoogleApiClient.connect();
updateProfile(false);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.signin:
googlePlusLogin();
break;
}
}
public void signIn(View v) {
googlePlusLogin();
}
private void googlePlusLogin() {
if (!mGoogleApiClient.isConnecting()) {
signedInUser = true;
resolveSignInError();
}
}
private void googlePlusLogout() {
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
updateProfile(false);
}
}
// download Google Account profile image, to complete profile
private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> {
ImageView downloadedImage;
public LoadProfileImage(ImageView image) {
this.downloadedImage = image;
}
protected Bitmap doInBackground(String... urls) {
String url = urls[0];
Bitmap icon = null;
try {
InputStream in = new java.net.URL(url).openStream();
icon = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return icon;
}
protected void onPostExecute(Bitmap result) {
downloadedImage.setImageBitmap(result);
}
}
And My homepageactvity is
public class HomePageActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,View.OnClickListener,
GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener
{
private SharedPreferences preferences;
ConnectionDetector cd;
AlertDialogManager alert = new AlertDialogManager();
private GoogleApiClient mGoogleApiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
cd = new ConnectionDetector(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View header=navigationView.getHeaderView(0);
TextView username=(TextView) header.findViewById(R.id.username);
TextView user_email=(TextView) header.findViewById(R.id.email);
ImageView profileImage=(ImageView) header.findViewById(R.id.imageView) ;
String user_name= getIntent().getStringExtra("username");
String user_gmail= getIntent().getStringExtra("email");
String profile_pic=getIntent().getStringExtra("profile_pic");
username.setText(user_gmail);
user_email.setText(user_name);
CardView card_attendance = (CardView) findViewById(R.id.card_attendance);
CardView card_assignment = (CardView) findViewById(R.id.card_assignment);
CardView card_circular = (CardView) findViewById(R.id.card_circular);
CardView card_communication = (CardView) findViewById(R.id.card_communication);
CardView card_Fee = (CardView) findViewById(R.id.card_Fee);
CardView card_Library = (CardView) findViewById(R.id.card_Library);
CardView card_Result = (CardView) findViewById(R.id.card_Result);
CardView card_StudyMat = (CardView) findViewById(R.id.card_StudyMat);
card_attendance.setOnClickListener(this);
card_assignment.setOnClickListener(this);
card_circular.setOnClickListener(this);
card_communication.setOnClickListener(this);
card_Fee.setOnClickListener(this);
card_Library.setOnClickListener(this);
card_Result.setOnClickListener(this);
card_StudyMat.setOnClickListener(this);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(new Scope(Scopes.PROFILE))
.addScope(new Scope(Scopes.EMAIL))
.build();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.home_page, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_change_pass) {
Intent intent = new Intent(HomePageActivity.this, ChangePasswordActivity.class);
startActivity(intent);
} else if (id == R.id.nav_logout) {
googlePlusLogout();
}
else if (id == R.id.nav_faq) {
Intent intent = new Intent(HomePageActivity.this, FAQActivity.class);
startActivity(intent);
} else if (id == R.id.nav_about) {
PopupAbout();
} else if (id == R.id.nav_share) {
shareApp();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.card_attendance:
Intent intent = new Intent(HomePageActivity.this, AttendanceActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
case R.id.card_assignment:
Intent intent2 = new Intent(HomePageActivity.this, AssignmentActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent2);
break;
case R.id.card_StudyMat:
Intent intent3 = new Intent(HomePageActivity.this, StudyMaterialListActivity.class);
intent3.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent3);
break;
case R.id.card_Library:
Intent intent4 = new Intent(HomePageActivity.this, LibraryActivity.class);
intent4.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent4);
break;
case R.id.card_Result:
Intent intent5 = new Intent(HomePageActivity.this, ResultActivity.class);
intent5.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent5);
break;
case R.id.card_communication:
Intent intent6 = new Intent(HomePageActivity.this, CommunicationActivity.class);
intent6.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent6);
break;
case R.id.card_Fee:
Intent intent7=new Intent(HomePageActivity.this,FeeActivity.class);
intent7.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent7);
break;
case R.id.card_circular:
Intent intent8=new Intent(HomePageActivity.this,CircularListActivity.class);
intent8.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent8);
break;
default:
break;
}
}
private void shareApp() {
try {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("text/plain");
i.putExtra(Intent.EXTRA_SUBJECT, "Checkout The NI Model School App for Android");
String sAux = "\nHi, I am using The NI Model School Android app to track my child's activities in school.\n";
String sAux1 = sAux + "Why don't you check it out on your Android phone.\n";
String sAux2 = sAux1 + "market://details?id="
+ HomePageActivity.this.getPackageName() + "\n\n";
i.putExtra(Intent.EXTRA_TEXT, sAux2);
startActivity(Intent.createChooser(i, "choose one"));
} catch (Exception e) {
e.printStackTrace();
}
}
private void PopupAbout() {
AlertDialog.Builder alertDialogBuilder1 = new AlertDialog.Builder(
HomePageActivity.this);
alertDialogBuilder1.setTitle(R.string.app_name);
LayoutInflater li = LayoutInflater.from(HomePageActivity.this);
final View pView = li.inflate(R.layout.alert_about, null);
alertDialogBuilder1.setView(pView);
alertDialogBuilder1.setIcon(R.mipmap.ic_launcher);
alertDialogBuilder1.setCancelable(true);
try {
PackageInfo pInfo = HomePageActivity.this.getPackageManager()
.getPackageInfo(HomePageActivity.this.getPackageName(), 0);
String version = pInfo.versionName;
alertDialogBuilder1.setMessage("Version: " + version);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
alertDialogBuilder1.setPositiveButton("Rate",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
Uri uri = Uri.parse("market://details?id="
+ HomePageActivity.this.getPackageName());
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
goToMarket.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
try {
startActivity(goToMarket);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Toast.makeText(HomePageActivity.this,
"Play Store unavailable..",
Toast.LENGTH_LONG).show();
}
}
});
AlertDialog alertDialog = alertDialogBuilder1.create();
alertDialog.show();
}
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
} private void googlePlusLogout() {
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
Intent intent = new Intent(HomePageActivity.this, LoginActivityGoogle.class);
startActivity(intent);
}
}

remove the selected line in image from your code

I resolved the above issue,actually the app got crashr=ed because i didn't connect google client in to my Homepageactvity.So once i coonected the google client in to my Homepageactvity,then i can log out from my app.
First i intailthe below codes in to my On create method
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.DRIVE_APPFOLDER))
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
After that i called the method for googlesignout.Its working fine now

Related

Getting NullPointerException when setting TextView values from SharedPreferences [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Here is my SignInActivityCode
public class SignInActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {
GoogleApiClient mGoogleApiClient;
private static final int RC_SIGN_IN=0;
private String TAG = "SignInActivity";
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signin_activity);
try{
getSupportActionBar().hide();
}catch (Exception e){
e.printStackTrace();
}
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
SignInButton signInButton = (SignInButton) findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
signInButton.setOnClickListener(this);
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.sign_in_button:
signIn();
break;
}
}
private void signIn(){
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN){
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInIntent(result);
}
}
private void handleSignInIntent(GoogleSignInResult result){
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if(result.isSuccess()){
GoogleSignInAccount acct = result.getSignInAccount();
Toast.makeText(this, "Sign in successful!", Toast.LENGTH_LONG).show();
setDefaults(acct.getDisplayName(), acct.getEmail(), acct.getIdToken());
Intent intent = new Intent(SignInActivity.this, MainActivity.class);
startActivity(intent);
}
else{
Toast.makeText(this, "Sign In Failed!\nPlease try again.", Toast.LENGTH_LONG).show();
}
}
public void setDefaults(String name, String email, String token){
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("userName", name);
editor.putString("userEmail", email);
editor.putString("userIdToken", token);
editor.apply();
}
}
and here is how I am applying the information passed to the MainActivity in my nav_header_main.xml file
#Override
protected void onCreate(Bundle savedInstanceState) {
initializeUserInfo();
}
private void initializeUserInfo() {
userName = (TextView) findViewById(R.id.nav_user_name_tv);
userEmail = (TextView) findViewById(R.id.nav_user_email_tv);
final SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
name = sharedPref.getString("userName", "");
email = sharedPref.getString("userEmail", "");
try{
userName.setText(name);
userEmail.setText(email);
}catch(Exception e){
e.printStackTrace();
}
}
and the error that I am getting in the logs
Blockquote
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
This is how you initialize and declare navigation view items
private NavigationView navigationView;
private DrawerLayout drawer;
private View navHeader;
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.nav_view);
// Navigation view header
navHeader = navigationView.getHeaderView(0);
txtName = (TextView) navHeader.findViewById(R.id.nameNav);

Intent activity after facebook login opened twice

I have a main activity that displays login option, if the user clicked login with FB button, I will call fblogin();, and if the login success then I will do intent to open home activity.
right now, the home activity seems to open twice. (i can see it appear twice, stacked)
private void Fblogin()
{
callbackmanager = CallbackManager.Factory.create();
// Set permissions
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile, email, user_birthday,user_friends"));
LoginManager.getInstance().registerCallback(callbackmanager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
Log.d("LoginActivity", response.toString());
Log.d("LoginActivity", object.toString());
String jsonresult = String.valueOf(object);
System.out.println("JSON Result" + jsonresult);
String str_firstname=null,str_id=null;
try {
str_firstname=object.getString("name");
str_id = object.getString("id");
String str_email = object.getString("email");
Intent home = new Intent(MainActivity.this , HomeActivity.class);
home.putExtra("name", str_firstname);
home.putExtra("URL", "https://graph.facebook.com/" + str_id + "/picture?width="+PROFILE_PIC_SIZE+"&height="+PROFILE_PIC_SIZE);
startActivity(home);
} catch (JSONException e) {
e.printStackTrace();
Log.d("xxxx","aa");
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender, birthday");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
Log.v("LoginActivity", "cancel");
}
#Override
public void onError(FacebookException exception) {
Log.v("LoginActivity", exception.getCause().toString());
}
});
}
in my main activity, i call this in my on create FacebookSdk.sdkInitialize(getApplicationContext());
, iI also check for initial login status `
if ( AccessToken.getCurrentAccessToken() != null && Profile.getCurrentProfile()!=null ) {
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);}
but I think that initial check has nothing to do with it becauseI tried to delete it too but it still happening.`
and in my Home Activity, I have not write any facebook related codes yet.
EDIT : I PUT WHOLE CODE (MainActivity)
import ...
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static Boolean IsLoggedFB = false; //general state of fb logged
public static Boolean IsLoggedManual =false; //status boolean if logged in by email (manual)
public static Boolean IsLoggedGM = false; //general state of google gmail logged
String ID_HNBS; //IDhnbs created when first Registered
String Email;
TextView Fpassword;
Button Daftar;
EditText email, password;
Button LoginEmail;
LoginButton fb_button;
SignInButton gplus_button;
MainActivity myContext;
static String personName;
private boolean mIntentInProgress;
FragmentManager fragmentManager;
private CallbackManager callbackmanager;
//for G+
private GoogleSignInOptions gso;
private static final int PROFILE_PIC_SIZE = 30;
private GoogleApiClient mGoogleApiClient;
private ConnectionResult mConnectionResult;
private boolean mSignInClicked;
static final int RC_SIGN_IN = 0;
/* Is there a ConnectionResult resolution in progress? */
private boolean mIsResolving = false;
LinearLayout tv;
/* Should we automatically resolve ConnectionResults when possible? */
private boolean mShouldResolve = false;
public static final String MyPREFERENCES = "xpp";
SharedPreferences sharedpreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
setContentView(R.layout.activity_main);
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
IsLoggedManual = sharedpreferences.getBoolean("IsLoggedManual", false); // get value of last login status
IsLoggedGM = sharedpreferences.getBoolean("IsloggedGM", false); // get value of last login GM
Daftar = (Button) findViewById(R.id.buttonDaftarEmail);
LoginEmail = (Button) findViewById(R.id.buttonLoginEmail);
fb_button = (LoginButton)findViewById(R.id.fblogin_button);
//Initializing google signin option
gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
gplus_button = (SignInButton) findViewById(R.id.sign_in_button);
gplus_button.setSize(SignInButton.SIZE_STANDARD);
gplus_button.setScopes(gso.getScopeArray());
//Initializing google api client
mGoogleApiClient = new GoogleApiClient.Builder(this)
//.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
Daftar.setOnClickListener(this);
LoginEmail.setOnClickListener(this);
fb_button.setOnClickListener(this);
gplus_button.setOnClickListener(this);
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone())
{
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d("TAG", "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
}
Log.d("TAG", "ACCESS TOKEN STATUS" + AccessToken.getCurrentAccessToken() + " --- profile=" + Profile.getCurrentProfile());
//CHECK IF ALREADY LOGGED BY FB
if ( AccessToken.getCurrentAccessToken() != null && Profile.getCurrentProfile()!=null ) {
//load profile and skip (loginfragment) to Home page
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);
} else if ( IsLoggedManual ) { //IF already LOGGED IN MANUAL (SHAREDPREF)
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);
}
}
#Override
public void onClick(View v) {
if (v.getId() == R.id.buttonDaftarEmail) {
Intent intent = new Intent(MainActivity.this, UserRegistration.class);
startActivity(intent);
} else if (v.getId() == R.id.buttonLoginEmail) {
Intent intent_signin = new Intent(MainActivity.this, LoginManual.class);
startActivity(intent_signin);
} else if (v.getId() == R.id.fblogin_button) {
Fblogin();
} else if (v.getId() == R.id.sign_in_button) //google sign in button
{
Intent intent_Gsignin = new Intent(MainActivity.this, GSignIn.class);
startActivity(intent_Gsignin);
}
}
private void onSignInClicked() {
// User clicked the sign-in button, so begin the sign-in process and automatically
// attempt to resolve any errors that occur.
mShouldResolve = true;
mGoogleApiClient.connect();
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onStop() {
super.onStop();
}
private void Fblogin()
{
callbackmanager = CallbackManager.Factory.create();
// Set permissions
LoginManager.getInstance().logInWithReadPermissions(this, Arrays.asList("public_profile, email, user_birthday,user_friends"));
LoginManager.getInstance().registerCallback(callbackmanager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
// App code
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(),
new GraphRequest.GraphJSONObjectCallback() {
#Override
public void onCompleted(JSONObject object, GraphResponse response) {
// Application code
Log.d("LoginActivity", response.toString());
Log.d("LoginActivity", object.toString());
String jsonresult = String.valueOf(object);
System.out.println("JSON Result" + jsonresult);
String str_firstname=null,str_id=null;
try {
str_firstname=object.getString("name");
str_id = object.getString("id");
String str_email = object.getString("email");
Intent home = new Intent(MainActivity.this , HomeActivity.class);
home.putExtra("name", str_firstname);
home.putExtra("URL", "https://graph.facebook.com/" + str_id + "/picture?width="+PROFILE_PIC_SIZE+"&height="+PROFILE_PIC_SIZE);
startActivity(home);
} catch (JSONException e) {
e.printStackTrace();
Log.d("xxxx","aa");
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "id,name,email,gender, birthday");
request.setParameters(parameters);
request.executeAsync();
}
#Override
public void onCancel() {
Log.v("LoginActivity", "cancel");
}
#Override
public void onError(FacebookException exception) {
Log.v("LoginActivity", exception.getCause().toString());
}
});
}
//After the signing we are calling this function
private void handleSignInResult(GoogleSignInResult result) {
//If the login succeed
if (result.isSuccess()) {
//Getting google account
GoogleSignInAccount acct = result.getSignInAccount();
//tv= (LinearLayout) tv.findViewById(R.id.layoutfragmentlogin);
//tv.setVisibility(View.GONE); //hide include , so include now show nothing
Intent Home=new Intent(this,HomeActivity.class);
Home.putExtra("name",acct.getDisplayName());
Home.putExtra("email", acct.getEmail());
Home.putExtra("URL",acct.getPhotoUrl());
startActivity(Home);
} else {
//If login fails
Toast.makeText(this, "Login Failed on silentsign in", Toast.LENGTH_LONG).show();
}
}
//#Override
public void onConnected(Bundle bundle) {
mSignInClicked = false;
Toast.makeText(myContext, "User is connected!", Toast.LENGTH_LONG).show();
}
//#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(callbackmanager!=null) {
callbackmanager.onActivityResult(requestCode, resultCode, data);
Log.d("ani", "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
}
if (requestCode == RC_SIGN_IN) {
// If the error resolution was not successful we should not resolve further.
if (resultCode != this.RESULT_OK) {
mShouldResolve = false;
}
mIsResolving = false;
mGoogleApiClient.connect();
}
}
//#Override
public void onConnectionFailed(ConnectionResult connectionResult)
{
//prefs.edit().putBoolean("Islogin",false).commit();
//DO Nothing..
/*
//==========Below is Trying to connect if googleUser not connected already =======
// Could not connect to Google Play Services. The user needs to select an account,
// grant permissions or resolve an error in order to sign in. Refer to the javadoc for
// ConnectionResult to see possible error codes.
Log.d("ani", "onConnectionFailed:" + connectionResult);
if (!mIsResolving && mShouldResolve) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(getActivity(), RC_SIGN_IN);
mIsResolving = true;
} catch (IntentSender.SendIntentException e) {
Log.e("ani", "Could not resolve ConnectionResult.", e);
mIsResolving = false;
mGoogleApiClient.connect();
}
}
}*/
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setTitle("HnBS Alert")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finishAffinity();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
EDIT 2 : MY HOMEACTIVITY CODE
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
/**
* react to the user tapping/selecting an options menu item
*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_menu_logout:
LoginManager.getInstance().logOut(); //LogOut from Facebook
//logout from login manual
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean("IsLoggedManual",false).commit();
//if (mGoogleApiClient.isConnected()) {
// if (mGoogleApiClient.isConnected())
// Auth.GoogleSignInApi.signOut(mGoogleApiClient);
//}
Toast.makeText(this, "LoggedOut!", Toast.LENGTH_SHORT).show();
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finishAffinity();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
After eight hours trial with some debugging, i couldn't find any trace of what is causing my HomeActivity fires twice. for people who stuck in any similar case, if you want and if its not breaking out your code, you can try to make your activity appear only one instance by adding this on your activity declaration in the manifest:
android:launchMode = "singleTask"
this has been the solution for me right now cause i don't want to waste any time longer as i need to move on to the next progress. thank you for any assistance.
You are calling the activity twice. That is
when consider if you are logged in facebook and google then the both the code get executed.
in onCreate you are calling
if (opr.isDone())
{
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d("TAG", "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result); //check method for going to home activity
}
and
if ( AccessToken.getCurrentAccessToken() != null && Profile.getCurrentProfile()!=null ) {
//load profile and skip (loginfragment) to Home page
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);
} else if ( IsLoggedManual ) { //IF already LOGGED IN MANUAL (SHAREDPREF)
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);
}
Use these conditions as one eg
opr.isDone() || AccessToken.getCurrentAccessToken() != null && Profile.getCurrentProfile()!=null
Here you missed it, check out this code -
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d("TAG", "Got cached sign-in");
GoogleSignInResult result = opr.get();
handleSignInResult(result);
}
Above cached sign-in will start HomeActivity as well as if your AccessToken is not null(you're logged in with facebook) - again will start Home Activity
//CHECK IF ALREADY LOGGED BY FB
if ( AccessToken.getCurrentAccessToken() != null && Profile.getCurrentProfile()!=null ) {
//load profile and skip (loginfragment) to Home page
Intent home = new Intent(MainActivity.this , HomeActivity.class);
startActivity(home);
}
Solution:
You should put these conditions using else if ladder statements...

Error in Re-login with Google after logout in Android

Hi I use Google login in my app it works fine but whenever I logging out I tried many solution for logging out but it doesn't works for me and if I further clicks on Google login button then app crashes.
Here is my code for Login
public class LoginActivity extends Activity implements AsyncInterface,
OnClickListener, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
EditText etLoginEmail, etLoginPassword;
Button btnLoginSubmit, btnLoginSignup;
TextView txtLoginForgotPass;
LoginResponseMain loginResponseMain;
/* For Google */
private static final int RC_SIGN_IN = 0;
private GoogleApiClient mGoogleApiClient;
private boolean mIntentInProgress;
private boolean mSignInClicked;
private ConnectionResult mConnectionResult;
private SignInButton btnSignIn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
init();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
// Google Sign In Button
btnSignIn.setOnClickListener(this);
}
#Override
protected void onStart() {
super.onStart();
if (AppMethod.getBooleanPreference(LoginActivity.this, AppConstant.PREF_FIRST_LOGIN)) {
//startActivity(new Intent(LoginActivity.this, HomePage.class));
} else {
mGoogleApiClient.connect();
}
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
public void init() {
loginResponseMain = new LoginResponseMain();
btnSignIn = (SignInButton) findViewById(R.id.sign_in_button);
}
#Override
public void onWSResponse(String json, String WSType) {
if (WSType == AppConstant.WS_LOGIN_G) {
try {
Log.e("Json", json);
JSONObject jobj = new JSONObject(json);
boolean error = jobj.getBoolean("error");
if (!error) {
JSONArray jsonArray = jobj.getJSONArray("user");
JSONObject jobjUser = jsonArray.getJSONObject(0);
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_FACEBOOK_ID, jobjUser.getString("facebook_id"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_GOOGLE_ID, jobjUser.getString("google_plus_id"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_EMAIL, jobjUser.getString("email"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_FNAME, jobjUser.getString("first_name"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_LNAME, jobjUser.getString("last_name"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_UPDATED_AT, jobjUser.getString("updated_at"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_CREATED_AT, jobjUser.getString("created_at"));
AppMethod.setStringPreference(LoginActivity.this, AppConstant.PREF_USER_ID, String.valueOf(jobjUser.getInt("id")));
Intent i = new Intent(LoginActivity.this, TermsForUseActivity.class);
startActivity(i);
finish();
} else {
Toast.makeText(LoginActivity.this, AppConstant.SOMETHING_WRONG_TRY_AGAIN, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public void onConnected(Bundle bundle) {
mSignInClicked = false;
getProfileInformation();
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
public void onClick(View v) {
switch (v.getId()) {
// Login Button Click
case R.id.sign_in_button:
signInWithGplus();
break;
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (!connectionResult.hasResolution()) {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result2 = googleAPI.isGooglePlayServicesAvailable(this);
if (result2 != ConnectionResult.SUCCESS) {
if (googleAPI.isUserResolvableError(result2)) {
googleAPI.getErrorDialog(this, result2, 0).show();
}
}
return;
}
if (!mIntentInProgress) {
mConnectionResult = connectionResult; // Store the ConnectionResult for later usage
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();
}
}
}
#Override
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();
}
}
}
/* Fetching user's information name, email, profile pic */
private void getProfileInformation() {
try {
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
String url = AppConstant.LOGIN_WITH_G;
// WS for google login data submit.
if (AppMethod.isNetworkConnected(LoginActivity.this)) {
String android_id = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
String device_token = AppMethod.registerForGCM(LoginActivity.this);
Uri.Builder values = new Uri.Builder()
.appendQueryParameter("first_name", personName)
.appendQueryParameter("email", email)
.appendQueryParameter("udid", android_id)
.appendQueryParameter("login_type", "0")
.appendQueryParameter("device_token", device_token)
.appendQueryParameter("google_plus_id", currentPerson.getId());
WsHttpPostWithNamePair wsHttpPost = new WsHttpPostWithNamePair(LoginActivity.this, AppConstant.WS_LOGIN_G, values);
wsHttpPost.execute(url);
} else {
Toast.makeText(LoginActivity.this, AppConstant.NO_INTERNET_CONNECTION, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getApplicationContext(), "Person information is null", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void signInWithGplus() {
if (!mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInError();
}
}
private void resolveSignInError() {
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
} catch (IntentSender.SendIntentException e) {
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
}
Now i need to signout from another activity use this code
For Logging out
public class HomePage extends TabActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener,
ResultCallback<People.LoadPeopleResult> {
DrawerLayout dLayout;
LinearLayout right_layout;
Button btnViewProfile, btnLogout;
//Google
GoogleApiClient mGoogleApiClient;
private boolean mIntentInProgress;
private ConnectionResult mConnectionResult;
private static final int RC_SIGN_IN = 0;
private boolean mSignInClicked;
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.home_page);
llHomePageMain = (LinearLayout) findViewById(R.id.llHomePageMain);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(Plus.API)
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
mGoogleApiClient.connect();
dLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
right_layout = (LinearLayout) findViewById(R.id.right_layout);
btnViewProfile = (Button) findViewById(R.id.btnViewProfile);
btnLogout = (Button) findViewById(R.id.btnLogout);
btnViewProfile.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("Right Layout", "Profile");
dLayout.closeDrawer(Gravity.END);
Intent i = new Intent(HomePage.this, ProfileActivity.class);
startActivity(i);
}
});
btnLogout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AppMethod.clearApplicationData(HomePage.this);
googlePlusLogout();
loginSessionClear();
}
}
});
}
#Override
public void onConnected(Bundle bundle) {
mSignInClicked = false;
}
private void resolveSignInError() {
if (mConnectionResult != null)
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
} catch (IntentSender.SendIntentException e) {
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
private void googlePlusLogout() {
if (mGoogleApiClient != null)
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (!connectionResult.hasResolution()) {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int result2 = googleAPI.isGooglePlayServicesAvailable(this);
if (result2 != ConnectionResult.SUCCESS) {
if (googleAPI.isUserResolvableError(result2)) {
googleAPI.getErrorDialog(this, result2, 0).show();
}
}
return;
}
if (!mIntentInProgress) {
mConnectionResult = connectionResult;
if (mSignInClicked) {
resolveSignInError();
}
}
}
#Override
public void onBackPressed() {
dLayout.closeDrawers();
super.onBackPressed();
}
public void loginSessionClear() {
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_EMAIL, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_FNAME, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_LNAME, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_UDID, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_DEVICE_TOKEN, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_UPDATED_AT, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_CREATED_AT, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_GOOGLE_ID, "");
AppMethod.setStringPreference(HomePage.this, AppConstant.PREF_USER_ID, String.valueOf(""));
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
#Override
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();
}
}
}
#Override
public void onResult(People.LoadPeopleResult loadPeopleResult) {
}
}
This method doesnt work for me.
Even if i clear preference and try for new login with google then app crashes.
Logcat Error
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean com.google.android.gms.common.ConnectionResult.hasResolution()' on a null object reference
Check null first
private void resolveSignInError() {
if (mConnectionResult != null)
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
} catch (IntentSender.SendIntentException e) {
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
and call bellow method for Logout
private void googlePlusLogout() {
if (mGoogleApiClient != null)
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
}
}

Parse FB Login Crash on Function Not Included in Login

I have integrated Parse Login (v1.10.3) and never had this issue until I integrated FB Login (v4.8.2). If uninstall and re-install the app and launch, when the app launches I receive an error from an activity that occurs after Login. I have the MainActivity as the launch page and it checks for a current user. If the current user is null it redirects to the LoginActivity. The LoginActivity crashes with a Null Pointer Exception error that occurs in an Adapter linked to a Fragment called from the Main Adapter. Why is my Login Activity being skipped?
I have a lot of logs in my code as I was trying to determine if there is a current user value at some point or if there is any Login function executed that would cause it to skip the Login, but none of it is executed and the current user is always Null (which I expect).
Login Activity
public static final List<String> mPermissions = new ArrayList<String>() {
{
add("public_profile");
add("email");
add("gender");
add("user_birthday");
}};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//set and transition to signup page
mSignUpTextView = (TextView)findViewById(R.id.signupText);
mSignUpTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(LoginActivity.this, SignupActivity.class);
startActivity(intent);
}
});
//set and transition to reset password page
mResetPasswordText = (TextView)findViewById(R.id.login_ForgotPasswordText);
mResetPasswordText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(LoginActivity.this, ResetPasswordActivity.class);
startActivity(intent);
}
});
//set and handle all login tasks
mUsername = (EditText)findViewById(R.id.usernameField);
mPassword = (EditText)findViewById(R.id.passwordField);
mLoginButton = (Button)findViewById(R.id.loginButton);
//Facebook login
loginButton = (LoginButton) findViewById(R.id.login_button);
loginButton.setReadPermissions(Arrays.asList("public_profile, email, user_birthday, user_friends"));
callbackManager = CallbackManager.Factory.create();
mFbProfile = Profile.getCurrentProfile();
Log.d("Login FB", String.valueOf(mFbProfile));
// Other app specific specialization
// Callback registration
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ParseFacebookUtils.logInWithReadPermissionsInBackground(LoginActivity.this, mPermissions, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
Log.d("Login", "Uh oh. The user cancelled the Facebook login.");
if (err != null) {
Log.d("ParseFacebookLogin", "Error: " + err.getLocalizedMessage());
}
}
else if (user.isNew()) {
Log.d("Login", "User signed up and logged in through Facebook!");
getUserDetailsFromFB();
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Log.d("Login FB", "User logged in through Facebook!");
}
else {
Log.d("Login", "User logged in through Facebook!");
getUserDetailsFromParse();
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
}
});
}
});
//Regular Parse Login ----------------------------------------------------------
mLoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String username = mUsername.getText().toString();
String password = mPassword.getText().toString();
username = username.trim();
password = password.trim();
//noinspection StatementWithEmptyBody
if (username.isEmpty() || password.isEmpty()){
// display message if field is blank
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage(R.string.login_error_message)
.setTitle(R.string.login_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
else {
// login user
ParseUser.logInInBackground(username, password, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
//success
FlokkApp.updateParseInstallation(user);
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
//Toast.makeText(LoginActivity.this, "Successful Login", Toast.LENGTH_SHORT).show();
}
else {
AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this);
builder.setMessage(e.getMessage())
.setTitle(R.string.login_error_title)
.setPositiveButton(android.R.string.ok, null);
AlertDialog dialog = builder.create();
dialog.show();
}
}
});
}
}
});
}
//Facebook login required below ------------------------------------
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("Login", "on activity result");
super.onActivityResult(requestCode, resultCode, data);
ParseFacebookUtils.onActivityResult(requestCode, resultCode, data);
}
//Facebook save new user code -----------------------------------------------
private void saveNewUser() {
Log.d("Login", "Save new user");
parseUser = ParseUser.getCurrentUser();
parseUser.setUsername(name);
parseUser.setEmail(email);
//will need to update once I figure out how facebook sends the data
boolean genderValue;
if (gender == "Male") {
genderValue = true;
} else {
genderValue = false;
};
parseUser.put(ParseConstants.KEY_GENDERMALE, genderValue);
String searchtext = name.toLowerCase().trim();
parseUser.put(ParseConstants.KEY_SEARCHTEXT, searchtext);
//Saving profile photo as a ParseFile
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bitmap = null; //((BitmapDrawable) mProfileImage.getDrawable()).getBitmap();
if (bitmap != null) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
byte[] data = stream.toByteArray();
String thumbName = parseUser.getUsername().replaceAll("\\s+", "");
final ParseFile parseFile = new ParseFile(thumbName + "_android_FBLogin.jpg", data);
parseFile.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
parseUser.put(ParseConstants.KEY_PROFILEPIC, parseFile);
//Finally save all the user details
parseUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
Toast.makeText(LoginActivity.this, "New user:" + name + " Signed up", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
private void getUserDetailsFromFB() {
Log.d("Login", "getUserDetails From FB");
// Suggested by https://disqus.com/by/dominiquecanlas/
Bundle parameters = new Bundle();
parameters.putString("fields", "email,name,gender,picture");
new GraphRequest(
AccessToken.getCurrentAccessToken(),
"/me",
parameters,
HttpMethod.GET,
new GraphRequest.Callback() {
public void onCompleted(GraphResponse response) {
/* handle the result */
try {
Log.d("Response", response.getRawResponse());
email = response.getJSONObject().getString("email");
//mEmailID.setText(email);
name = response.getJSONObject().getString("name");
mUsername.setText(name);
gender = response.getJSONObject().getString("gender");
JSONObject picture = response.getJSONObject().getJSONObject("picture");
JSONObject data = picture.getJSONObject("data");
// Returns a 50x50 profile picture
String pictureUrl = data.getString("url");
Log.d("Profile pic", "url: " + pictureUrl);
new ProfilePhotoAsync(pictureUrl).execute();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
).executeAsync();
}
private void getUserDetailsFromParse() {
Log.d(" Login", "getUserDetails From parse");
parseUser = ParseUser.getCurrentUser();
//Fetch profile photo
try {
ParseFile parseFile = parseUser.getParseFile(ParseConstants.KEY_PROFILEPIC);
byte[] data = parseFile.getData();
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
//mProfileImage.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
//mEmailID.setText(parseUser.getEmail());
mUsername.setText(parseUser.getUsername());
//Toast.makeText(LoginActivity.this, "Welcome back " + mUsername.getText().toString(), Toast.LENGTH_SHORT).show();
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_login, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//Required for facebook
class ProfilePhotoAsync extends AsyncTask<String, String, String> {
public Bitmap bitmap;
String url;
public ProfilePhotoAsync(String url) {
this.url = url;
}
#Override
protected String doInBackground(String... params) {
// Fetching data from URI and storing in bitmap
bitmap = DownloadImageBitmap(url);
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//mProfileImage.setImageBitmap(bitmap);
saveNewUser();
}
}
public static Bitmap DownloadImageBitmap(String url) {
Bitmap bm = null;
try {
URL aURL = new URL(url);
URLConnection conn = aURL.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
} catch (IOException e) {
Log.e("IMAGE", "Error getting bitmap", e);
}
return bm;
}
Main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ParseAnalytics.trackAppOpened(getIntent());
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null) {
navigateToLogin();
Log.d("Login Check", String.valueOf(ParseUser.getCurrentUser()));
}
else {
}
toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(new MyPagerAdapter(getSupportFragmentManager()));
mTabs = (SlidingTabLayout) findViewById(R.id.tabs);
mTabs.setDistributeEvenly(true);
mTabs.setViewPager(mPager);
try {
PackageInfo info = getPackageManager().getPackageInfo(
"com.myflokk.testflokkd",
PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (PackageManager.NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}
}
//included onResume as a part of facebook integration
#Override
protected void onResume() {
super.onResume();
// Logs 'install' and 'app activate' App Events.
AppEventsLogger.activateApp(this);
}
//included onPause as a part of facebook integration
#Override
protected void onPause() {
super.onPause();
// Logs 'app deactivate' App Event.
AppEventsLogger.deactivateApp(this);
}
private void navigateToLogin() {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
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.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will automatically handle clicks on the Home/Up button, so long as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
switch (id) {
case R.id.addEvent:
startActivity(new Intent(this, AddEventActivity.class));
break;
case R.id.editProfile:
startActivity(new Intent(this, UserProfileEditActivity.class));
break;
case R.id.action_logout:
ParseUser.logOut();
navigateToLogin();
break;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onStart() {
super.onStart();
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser == null) {
navigateToLogin();
Log.d("Login Check 2", String.valueOf(ParseUser.getCurrentUser()));
}
else {
}
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.myflokk.testflokkd/http/host/path")
);
AppIndex.AppIndexApi.start(client, viewAction);
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
Action viewAction = Action.newAction(
Action.TYPE_VIEW, // TODO: choose an action type.
"Main Page", // TODO: Define a title for the content shown.
// TODO: If you have web page content that matches this app activity's content,
// make sure this auto-generated web page URL is correct.
// Otherwise, set the URL to null.
Uri.parse("http://host/path"),
// TODO: Make sure this auto-generated app deep link URI is correct.
Uri.parse("android-app://com.myflokk.testflokkd/http/host/path")
);
AppIndex.AppIndexApi.end(client, viewAction);
client.disconnect();
}
class MyPagerAdapter extends FragmentPagerAdapter {
String[] tabs;
public MyPagerAdapter(FragmentManager fm) {
super(fm);
tabs = getResources().getStringArray(R.array.tabs);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new UserEventListFragment();
case 1:
return new UserSearchFragment();
case 2:
return new UserProfileActivityFragment();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
#Override
public int getCount() {
return 3;
}
}
Event Adapter that Causes the Error
protected Context mContext;
protected List<ParseObject> mEvents;
private SimpleDateFormat mFormat = new SimpleDateFormat("E, MMM d", Locale.US);
protected Date mDate;
protected List<Object> mLikeList = new ArrayList<>();
protected int mLikes = 0;
protected String Flokking = "I am flokking to this event!";
public EventAdapter(Context context, List<ParseObject> events) {
super(context, R.layout.row_event_list, events);
mContext = context;
mEvents = events;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.row_event_list, null);
holder = new ViewHolder();
holder.eventName = (TextView) convertView.findViewById(R.id.eventRow_TextEventName);
holder.eventLocation = (TextView) convertView.findViewById(R.id.eventRow_TextEventLocation);
holder.eventImage = (ImageView) convertView.findViewById(R.id.eventRow_EventImage);
holder.eventDate = (TextView) convertView.findViewById(R.id.eventRow_Date);
holder.eventNotLiked = (ImageView) convertView.findViewById(R.id.eventRow_ImageNotLiked);
holder.eventLiked = (ImageView) convertView.findViewById(R.id.eventRow_ImageLiked);
holder.eventFlokkingCount = (TextView) convertView.findViewById(R.id.eventRow_FlokkingCount);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ParseObject event = mEvents.get(position);
ParseObject details = mEvents.get(position);
final String currentEvent = details.getObjectId();
//Log.d("EventAdapter", "This is the position --> " + position);
holder.eventName.setText(event.getString(ParseConstants.KEY_EVENTNAME));
holder.eventLocation.setText(event.getString(ParseConstants.KEY_EVENTVENUE));
holder.eventFlokkingCount.setText(event.getNumber(ParseConstants.EVENT_LIKECOUNT).toString());
//get the date and assign to mDate and then change the way the date is displayed
mDate = event.getDate(ParseConstants.KEY_EVENTDATE);
holder.eventDate.setText(mFormat.format(mDate));
mLikeList = event.getList(ParseConstants.EVENT_LIKES);
Log.d("Login Event Check", String.valueOf(ParseUser.getCurrentUser()));
if (mLikeList == null || mLikeList.isEmpty()) {
//this is false and the user has not liked the event
holder.eventLiked.setVisibility(View.INVISIBLE);
holder.eventNotLiked.setVisibility(View.VISIBLE);
}
else {
//if there are users in the list check for the current user
if (mLikeList.contains(ParseUser.getCurrentUser().getObjectId())) {
// true
holder.eventLiked.setVisibility(View.VISIBLE);
holder.eventNotLiked.setVisibility(View.INVISIBLE);
}
else {
holder.eventLiked.setVisibility(View.INVISIBLE);
holder.eventNotLiked.setVisibility(View.VISIBLE);
}
}
Error Log
02-01 19:05:28.800 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myflokk.testflokkd, PID: 1933
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.parse.ParseUser.getObjectId()' on a null object reference
at com.myflokk.testflokkd.Adapters.EventAdapter.getView(EventAdapter.java:98)

Google+ Login Not working properly on Android fragment

I am working with google+ login to my application and when i done it using a activity its work charm and after that i move my code into a fragment and after that when i try to login to google+ its not working i have to open the fragment activity 2 times to login to the google+ can anyone tell me what happen the code to the fragment is added below
public class GooglePluseFragment extends Fragment implements
ConnectionCallbacks, OnConnectionFailedListener {
private static final int RC_SIGN_IN = 0;
private static final String TAG = "MainActivity";
private static final int PROFILE_PIC_SIZE = 800;
private GoogleApiClient mGoogleApiClient;
private boolean mIntentInProgress;
private boolean mSignInClicked;
private ConnectionResult mConnectionResult;
private SignInButton btnSignIn;
private Button btnSignOut;
private Context mContext;
private Activity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
mContext = getActivity().getApplicationContext();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.compund_google_pluse_fragment,
container, false);
btnSignIn = (SignInButton) view.findViewById(R.id.btn_sign_in);
btnSignOut = (Button) view.findViewById(R.id.btn_sign_out);
sharedPref = view.getContext().getSharedPreferences(
Constantz.SHEARED_PREFEREANCE, Context.MODE_PRIVATE);
mGoogleApiClient = new GoogleApiClient.Builder(view.getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).addApi(Plus.API, null)
.addScope(Plus.SCOPE_PLUS_LOGIN).build();
btnSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signInWithGplus();
}
});
btnSignOut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
signOutFromGplus();
}
});
return view;
}
#Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
#Override
public void onActivityResult(int requestCode, int responseCode,
Intent intent) {
if (requestCode == RC_SIGN_IN) {
if (responseCode != Activity.RESULT_OK) {
mSignInClicked = false;
}
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
}
}
#Override
public void onConnectionFailed(ConnectionResult result) {
if (!result.hasResolution()) {
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
mActivity, 0).show();
Log.e(TAG, "" + result.getErrorCode());
return;
}
if (!mIntentInProgress) {
mConnectionResult = result;
if (mSignInClicked) {
Log.e(TAG, "" + result.getErrorCode());
resolveSignInError();
}
}
}
#Override
public void onConnected(Bundle arg0) {
mSignInClicked = false;
getProfileInformation();
updateUI(true);
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
updateUI(false);
}
private void updateUI(boolean isSignedIn) {
if (isSignedIn) {
btnSignIn.setVisibility(View.GONE);
btnSignOut.setVisibility(View.VISIBLE);
} else {
btnSignIn.setVisibility(View.VISIBLE);
btnSignOut.setVisibility(View.GONE);
}
}
/**
* Sign-in into google
* */
private void signInWithGplus() {
if (!mGoogleApiClient.isConnecting()) {
mSignInClicked = true;
resolveSignInError();
}
}
/**
* Method to resolve any signin errors
* */
private void resolveSignInError() {
if (mConnectionResult.hasResolution()) {
try {
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(mActivity,
RC_SIGN_IN);
} catch (SendIntentException e) {
mIntentInProgress = false;
mGoogleApiClient.connect();
}
}
}
/**
* Fetching user's information name, email, profile pic
* */
private void getProfileInformation() {
try {
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null) {
Person currentPerson = Plus.PeopleApi
.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
String personPhotoUrl = currentPerson.getImage().getUrl();
String personGooglePlusProfile = currentPerson.getUrl();
String email = Plus.AccountApi.getAccountName(mGoogleApiClient);
Log.e(TAG, "Name: " + personName + ", plusProfile: "
+ personGooglePlusProfile + ", email: " + email
+ ", Image: " + personPhotoUrl + " user id:"
+ currentPerson.getId());
} else {
Toast.makeText(mContext, "Person information is null",
Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Sign-out from google
* */
private void signOutFromGplus() {
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
updateUI(false);
}
}
}
this is how i added framgent in the fragment activity
pluseFragment = new GooglePluseFragment();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.pluse_frame_layout, pluseFragment);
transaction.commit();
can somebody tell me what i have done wrong ? why i have to open the activity two times to login thank you
Finally found the answer, Problem was when the result activity call in the fragment was catch by the parent activity so you have to manually redirect the result to your fragment. Just have to add this line in your Parent Fragment Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == GooglePluseFragment.RC_SIGN_IN) {
GooglePluseFragment fragment = (GooglePluseFragment) getSupportFragmentManager()
.findFragmentById(R.id.pluse_frame_layout);
fragment.onActivityResult(requestCode, resultCode, data);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
Easy Solution for this ::
just create the static method in fragment
"
public static myOnActivityResult(int requestCode, int resultCode, Intent data){
.....Enter same code
}
and
call this method from Parant Activity on
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
.....
MyFragment.myOnActivityResult(requestCode,resultCode,data)
}
thats it

Categories

Resources