Как передать объект GoogleApiClient в другой вид деятельности - PullRequest
0 голосов
/ 07 июня 2018

В моем логине у меня есть кнопка входа в Google.Я проверил и работает отлично.У меня были другие кнопки для выхода из системы и отмены, и они тоже работали нормально.

Это мой код экрана входа в систему.

 import android.app.ProgressDialog;
 import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.gms.auth.api.Auth;
  import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
   import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.OptionalPendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;

import java.util.ArrayList;
 import java.util.List;

 public class MainActivity extends AppCompatActivity implements
    View.OnClickListener,
    GoogleApiClient.OnConnectionFailedListener
{

private static final String TAG = MainActivity.class.getSimpleName();
private static final int RC_SIGN_IN = 007;

private GoogleApiClient mGoogleApiClient;
private ProgressDialog mProgressDialog;

private SignInButton btnSignIn;

List<String> profile=new ArrayList<>();
private MyGoogleApi_Singleton myGoogleApi_singleton;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btnSignIn = (SignInButton) findViewById(R.id.sign_in_button);
    btnSignIn.setOnClickListener(this);

    updateUI(false);

    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();

    /* Customizing G+ button
    btnSignIn.setSize(SignInButton.SIZE_STANDARD);
    btnSignIn.setScopes(gso.getScopeArray());*/

    //Create a new objet to handle in all class
    myGoogleApi_singleton= new MyGoogleApi_Singleton();
    myGoogleApi_singleton.getInstance(mGoogleApiClient);
}


private void signIn()
{
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);

}


private void signOut()
{
    Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>()
            {
                @Override
                public void onResult(Status status)
                {
                    updateUI(false);
                }
            });
}

private void revokeAccess()
{
    Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>()
            {
                @Override
                public void onResult(Status status)
                {
                    updateUI(false);
                }
            });
}

private void handleSignInResult(GoogleSignInResult result)
{
    Log.d(TAG, "handleSignInResult:" + result.isSuccess());
    if (result.isSuccess())
    {
        // Signed in successfully, show authenticated UI.
        GoogleSignInAccount acct = result.getSignInAccount();

        String personName = acct.getDisplayName();
        String personPhotoUrl = acct.getPhotoUrl().toString();
        String email = acct.getEmail();
        String idnumber= acct.getId();

        Log.e(TAG, "Name: " + personName + ", email: " + email
                + ", Image: " + personPhotoUrl+ ", Id Number: "+ idnumber);
        //Save the data into the arraylist
        profile.add(idnumber);
        profile.add(personName);
        profile.add(email);
        profile.add(personPhotoUrl);

        //save into sharedpreferences
        StringBuilder stringBuilder = new StringBuilder();

        for (String s:profile)
        {
            stringBuilder.append(s);
            stringBuilder.append(",");
        }

        SharedPreferences sharpref = getSharedPreferences("ProfileList",0);
        SharedPreferences.Editor editor = sharpref.edit();
        editor.putString("ProfileList", stringBuilder.toString());
        editor.commit();

        goIndexScreen();
    } else
        {
        // Signed out, show unauthenticated UI.
        updateUI(false);
        }
}

@Override
public void onClick(View v)
{
    switch (v.getId())
    {
        case R.id.sign_in_button:
            signIn();
            break;

        default:
            break;
    }
}

@Override
public 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);
        handleSignInResult(result);
    }
}

@Override
public void onStart()
{
    super.onStart();

    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);
    } else
        {
        // If the user has not previously signed in on this device or the sign-in has expired,
        // this asynchronous branch will attempt to sign in the user silently.  Cross-device
        // single sign-on will occur in this branch.
        showProgressDialog();
        opr.setResultCallback(new ResultCallback<GoogleSignInResult>()
        {
            @Override
            public void onResult(GoogleSignInResult googleSignInResult)
            {
                hideProgressDialog();
                handleSignInResult(googleSignInResult);
            }
        });
    }
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
{
    // An unresolvable error has occurred and Google APIs (including Sign-In) will not
    // be available.
    Log.d(TAG, "onConnectionFailed:" + connectionResult);
}

//method to show a progress dialog during the SignIn
private void showProgressDialog()
{
    if (mProgressDialog == null)
    {
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setMessage("Loading...");
        mProgressDialog.setIndeterminate(true);
    }

    mProgressDialog.show();
}

//method to hide the progress dialog
private void hideProgressDialog()
{
    if (mProgressDialog != null && mProgressDialog.isShowing())
    {
        mProgressDialog.hide();
    }
}
//method to show or hide the buttons
private void updateUI(boolean isSignedIn)
{
    if (isSignedIn)
    {
        btnSignIn.setVisibility(View.GONE);


    } else
        {
        btnSignIn.setVisibility(View.VISIBLE);

        }
}
//method to go to next activity
private void goIndexScreen()
{
    Intent intent=new Intent(this,Index.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

}

После успешного входа приложение переходит к другому действию.Мне нужно выйти из этой операции, но мне нужен mGoogleApiClient от LoginActivity, и я не знаю, как я могу это сделать.

Я создал новый класс (singleton), здесь мой код

import com.google.android.gms.common.api.GoogleApiClient;

class MyGoogleApi_Singleton {
private static final String TAG = "GoogleApiClient";

private static MyGoogleApi_Singleton instance = null;

private static GoogleApiClient mGoogleApiClient = null;

private MyGoogleApi_Singleton(Context context) {
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(context)
            .enableAutoManage(this, this)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();

}

public static MyGoogleApi_Singleton getInstance(Context context) {

    if(instance == null) {
        instance = new MyGoogleApi_Singleton(context);

    }

    return instance;
}


//methods SingIn,SignOut and Revoke
public void Login(GoogleApiClient bGoogleApiClient){


}

public void Logout(){
    if(mGoogleApiClient.isConnected()) {
        Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
                new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                        Log.d("LOGOUT-RESULT","LOGOUT");
                    }
                });
    }

}

public void Revoke() {
    if ((mGoogleApiClient.isConnected())) {
        Auth.GoogleSignInApi.revokeAccess(mGoogleApiClient).setResultCallback(
                new ResultCallback<Status>() {
                    @Override
                    public void onResult(Status status) {
                    Log.d("REVOKE-RESULT","REVOKE");
                    }
                });
    }
}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}
}

Это код активности индекса

   import android.content.Intent;
   import android.content.SharedPreferences;
   import android.os.Bundle;
   import android.support.annotation.NonNull;
    import android.support.design.widget.FloatingActionButton;
   import android.support.design.widget.Snackbar;
   import android.util.Log;
   import android.view.View;
   import android.support.design.widget.NavigationView;
   import android.support.v4.view.GravityCompat;
   import android.support.v4.widget.DrawerLayout;
   import android.support.v7.app.ActionBarDrawerToggle;
   import android.support.v7.app.AppCompatActivity;
   import android.support.v7.widget.Toolbar;
   import android.view.Menu;
   import android.view.MenuItem;
   import android.widget.ImageView;
   import android.widget.TextView;

   import com.bumptech.glide.Glide;
   import com.google.android.gms.auth.api.Auth;
   import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
   import com.google.android.gms.common.ConnectionResult;
   import com.google.android.gms.common.api.GoogleApiClient;
   import com.google.android.gms.common.api.ResultCallback;
   import com.google.android.gms.common.api.Status;
   import com.google.android.gms.tasks.OnCompleteListener;
   import com.google.android.gms.tasks.Task;

   import java.util.ArrayList;
   import java.util.List;

 public class Index extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener {
private ImageView ivprofile;
private TextView tvname;
private TextView tvemail;
private TextView tvidnumber;
private String picprofile;
private String name;
private String idnumber;
private String email;
final List<String> profile = new ArrayList<String>();
private View headerview;

private GoogleApiClient mGoogleApiClient;
private MyGoogleApi_Singleton myGoogleApiSingleton;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_index);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    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.addDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    //create a headerview to conect to header of left menu
    headerview=navigationView.getHeaderView(0);

    ivprofile=(ImageView)headerview.findViewById(R.id.imageProfile);
    tvname=(TextView)headerview.findViewById(R.id.fullName);
    tvemail=(TextView)headerview.findViewById(R.id.email);
    tvidnumber=(TextView) headerview.findViewById(R.id.idNumber);

    //Load file saved by sharedpreferences into a new arraylist
    final SharedPreferences sharpref = getSharedPreferences("ProfileList",0);
    String Items = sharpref.getString("ProfileList","");
    String [] listItems = Items.split(",");
    for (int i=0;i<listItems.length;i++){
        profile.add(listItems[i]);
    }

    //get the profile

    idnumber=profile.get(0);
    name=profile.get(1);
    email=profile.get(2);
    picprofile=profile.get(3);

    Log.d("ArrayPerfil", name+email+idnumber+picprofile);

    tvname.setText(name);
    tvidnumber.setText(idnumber);
    tvemail.setText(email);
    Glide.with(this).load(picprofile).into(ivprofile);

    //get the mgoogleapiclient objet
    myGoogleApiSingleton=new MyGoogleApi_Singleton();
    mGoogleApiClient=myGoogleApiSingleton.get_GoogleApiClient();


@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.index, 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_camera) {
        // Handle the camera action
    } else if (id == R.id.nav_gallery) {

    } else if (id == R.id.nav_slideshow) {

    } else if (id == R.id.nav_manage) {

    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }else if (id == R.id.logout) {
        myGoogleApiSingleton.getInstance(context).Logout();
        goLoginScreen();
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}
//method to go to login screen
private void goLoginScreen() {
    Intent intent=new Intent(this,MainActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

}

Как вы сказали, я создал прозрачную активность.Я добавил метод handleSignInResult, потому что он вызывает метод OnActivityResult.

Это код:

public class GoogleActivity extends AppCompatActivity {
public static final int RC_SIGN_IN = 1000;

private static final String ACTION = "calling_action";

public static Intent getIntent(Context context, int action, Intent actionIntent) {
    Intent i = new Intent(context, GoogleActivity.class);
    i.putExtra(ACTION, action);
    i.putExtra(Intent.EXTRA_INTENT, actionIntent);
    return i;
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

    Intent actionIntent;
    int action = getIntent().getIntExtra(ACTION, 0);
    switch (action) {
        case RC_SIGN_IN:
            actionIntent = (Intent) getIntent().getExtras().get(Intent.EXTRA_INTENT);
            if (actionIntent != null)
                startActivityForResult(actionIntent, RC_SIGN_IN);
            break;
        case 0:
        default:
            break;
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case RC_SIGN_IN:
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            handleSignInResult(result);
            finish();
            return;
    }
}
private void handleSignInResult(GoogleSignInResult result)
{

    if (result.isSuccess())
    {
        // Signed in successfully
        Log.d("SIGNIN", "YOU ARE LOG IN");


    } else
    {
        // Signed out,
        Log.d("SIGNIN", "YOU ARE NOT LOG IN");
    }
}

}

Я жду вашей помощи!

Спасибо!

1 Ответ

0 голосов
/ 08 июня 2018

Это не плохая идея, на самом деле это вы должны сделать.Если вы хотите обрабатывать все действия и события из Google Auth, самый простой, элегантный, пригодный для многократного использования и проверяемый способ сделать это - заключить эту логику в одно или несколько выделенных для этого предложений.

Если у вас малодействия, которые вы могли бы инкапсулировать все из них только в одном классе Wrap.Например, вы можете создать класс GoogleSingInWrapper и использовать шаблон Singleton, чтобы убедиться, что во всем приложении есть только один экземпляр.

public class GoogleSingInWrapper {
   private static GoogleSingInWrapper instance;
   private GoogleApiClient mGoogleApiClient;

   private GoogleSingainWrapper() {
      // Private constructor to deny the creation of this object through the constructor and prevent creating more then one instance
      mGoogleApiClient = /*create your client here*/;
   }

   public static getInstance(/*params you need*/) {
      if(instance == null)
         instance = new GoogleSingInWrapper (/*params*/);
      return instance;
   }

   public void login(/*params*/) {
      // Login
   }

   // Other methods
}

То есть получить (и создать экземпляр, если не 't еще существует) экземпляр GoogleSingInWrapper, который вы используете:

GoogleSingInWrapper.gerInstance(/*params*/);

Теперь, если вы поместите все переменные и логику в этот класс, вы сможете получить к ним доступ из любого места.mGoogleApiClient должен быть в этой оболочке.

Теперь вы можете добавить все необходимые вам методы login, logout и revoke.

и использовать его следующим образом:

GoogleSingInWrapper.getInstance().login(/*params*/);
GoogleSingInWrapper.getInstance().logout(/*params*/);
GoogleSingInWrapper.getInstance().revoke(/*params*/);

Вы не должны использовать mGoogleApiClient напрямую, оно должно быть заключено в GoogleSingInWrapper.

РЕДАКТИРОВАТЬ

Когда я говорю mGoogleApiClient должен быть закрытым внутри GoogleSingInWrapper, это означает, что у вас не должно быть доступа к нему вне GoogleSingInWrapper класса.Если вы создаете GoogleSingInWrapper, но создаете метод с именем

public GoogleApiClient get_GoogleApiClient();

, у вас проблемы сохраняются, потому что вы все еще используете этот mGoogleApiClient во всех действиях.Вы не хотите этого, поэтому вы хотите быть отделенным от этого объекта во всех действиях.

После ваших правок я буду набирать здесь больше кода, но чем больше свободного кода я дам вам, тем меньше вы изучаете.

public class GoogleSingInWrapper {
   private static GoogleSingInWrapper instance;
   private GoogleApiClient mGoogleApiClient;

   private GoogleSingainWrapper(Context context) {
      // Private constructor to deny the creation of this object through the constructor and prevent creating more then one instance
      GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestEmail() 
        .build(); 

      mGoogleApiClient = new GoogleApiClient.Builder(context)
        .enableAutoManage(this, this)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build(); 
   }

   public static getInstance(Context context) {
      if(instance == null)
         instance = new GoogleSingInWrapper (/*params*/);
      return instance;
   }

   public void login(/*params*/) {
      // Login
   }

   // Other methods
   public void logout(){ 
      if(mGoogleApiClient.isConnected()) {
      Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
            new ResultCallback<Status>() {
                @Override 
                public void onResult(Status status) {
                    Log.d("LOGOUT-RESULT","LOGOUT");
                } 
            }); 
      }  
   }
}

Это должно выглядеть как ваш GoogleSingInWrapper.И, например, для вызова метода выхода из системы вы должны вызвать следующее:

if (id == R.id.logout) {
    GoogleSingInWrapper.getInstance(context).logout();
    goLoginScreen(); 
} 

Обратите внимание, что конструктор намеренно Private, потому что вы не хотите вызывать new GoogleSingInWrapper.Если вы делаете это, вы создаете несколько экземпляров этого объекта и нарушаете шаблон Singleton.

Также вы можете заметить, что некоторым процессам, таким как login, требуется Activity, потому что результатыразмещено в onActivityResult.Чтобы отделить вас GoogleSingInWrapper от всех ваших Activities, вы можете создать выделенный Activity для управления всеми onActivityResults.Это действие должно быть прозрачным и невидимым для пользователя.

Этого можно добиться с помощью следующего кода:

public class GoogleActivity extends AppCompatActivity {
  public static final int RC_SIGN_IN = 1000;

  private static final String ACTION = "calling_action";

  public static Intent getIntent(Context context, int action, Intent actionIntent) {
    Intent i = new Intent(context, GoogleActivity.class);
    i.putExtra(ACTION, action);
    i.putExtra(Intent.EXTRA_INTENT, actionIntent);
    return i;
  }

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

    Intent actionIntent;
    int action = getIntent().getIntExtra(ACTION, 0);
    switch (action) {
      case RC_SIGN_IN:
        actionIntent = (Intent) getIntent().getExtras().get(Intent.EXTRA_INTENT);
        if (actionIntent != null)
          startActivityForResult(actionIntent, RC_SIGN_IN);
        break;
      case 0:
      default:
        break;
    }
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
      case RC_SIGN_IN:
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        handleSignInResult(result);
        finish();
        return;
    }
  }
}

Затем установите прозрачную тему в манифесте для этого Activity:

<activity
        android:name=".data.drive.GoogleActivity"
        android:theme="@style/TransparentActivity"/>

И определите свой прозрачный стиль в своей папке values:

<style name="TransparentActivity" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>

Теперь вам нужно собрать все сделанные мной кусочки и создать конечный продукт, чтобы получитьэто работает.

...