Доступ к клиенту Google Plus из нескольких действий
Я разрабатываю приложение, в которое я интегрировал Google Plus. Пока все работает нормально, я могу получить профиль пользователя.
Но сейчас я хочу сделать следующее:
1) у меня два вида деятельности signInActivity
а также shareActivity
,
2) Если пользователь уже вошел в систему, используя signInActivity
тогда он не должен просить войти снова вshareActivity
и должен напрямую делиться контентом.
3) Если пользователь не вошел в signInActivity
и попытаться поделиться данными с помощью shareActivity
Затем приложение должно войти в систему пользователя, а затем только поделиться данными. В этом случае, если пользователь возвращается к signInActivity
тогда приложение должно показать, что "вы уже вошли"
Короче говоря, я хочу, чтобы пользовательский вход был центральным в приложении, так что, если он подписан как alrady, он должен быть доступен из любого действия.
Я слышал о токене доступа, но я не знаю, как его использовать, и в документе говорится, что срок его действия истекает через час, а это не то, чего я хочу.
Как я могу сделать центральный вход в Google Plus? Является ли это возможным? или мне нужно аутентифицировать пользователя в каждом действии?
3 ответа
Управление отдельным экземпляром GoogleApiClient в каждом действии не приведет к тому, что пользователю будет предложено войти в систему несколько раз.
Вход в Google+ (т. Е. GoogleApiClient) обеспечивает интерфейс с учетными записями Google на устройстве и основной службой служб Google Play - он не имеет состояния для экземпляра GoogleApiClient. Поэтому, как только учетная запись устройства будет аутентифицирована для вашего приложения, новые экземпляры GoogleApiClient получат доступ к тому же состоянию. GoogleApiClient специально разработан для облегчения доступа к центральному штату, управляемому службами Google Play.
Вам повезло с токенами доступа! Сервисы Google Play позаботятся обо всем управлении токенами. Таким образом, хотя токены доступа действуют только в течение одного часа, как вы говорите, если вы пытаетесь использовать свой PlusClient для доступа к API Google, а срок действия вашего токена доступа истек, службы Google Play прозрачно запросят у вас новый токен доступа и завершат вызов.
Взгляните на первую часть этого выступления по вводу / выводу Google для более подробной информации:
0. TL;DR
Для нетерпеливого кодера рабочую версию следующей реализации можно найти на GitHub. Это тот же ответ, который написан в другом сообщении о переполнении стека.
После переписывания кода активности входа в систему несколько раз во многих различных приложениях, простым (и не очень элегантным) решением было создание клиента API Google в качестве объекта класса приложения. Но, поскольку состояние соединения влияет на поток UX, я никогда не был доволен этим подходом.
Сводя нашу проблему только к концепции подключения, мы можем считать, что:
- Он скрывает клиент Google API.
- У него конечные состояния.
- Это (довольно) уникальный.
- Текущее состояние влияет на поведение приложения.
1. Прокси шаблон
Так как Connection
заключает в капсулу GoogleApiClient
, он будет реализовывать ConnectionCallbacks
а также OnConnectionFailedListener
:
@Override
public void onConnected(Bundle hint) {
changeState(State.OPENED);
}
@Override
public void onConnectionSuspended(int cause) {
changeState(State.CLOSED);
connect();
}
@Override
public void onConnectionFailed(ConnectionResult result) {
if (currentState.equals(State.CLOSED) && result.hasResolution()) {
changeState(State.CREATED);
connectionResult = result;
} else {
connect();
}
}
Действия могут общаться с классом Connection через методы connect
, disconnect
, а также revoke
, но их поведение определяется текущим состоянием. Для конечного автомата требуются следующие методы:
protected void onSignIn() {
if (!googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
googleApiClient.connect();
}
}
protected void onSignOut() {
if (googleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(googleApiClient);
googleApiClient.disconnect();
googleApiClient.connect();
changeState(State.CLOSED);
}
}
protected void onSignUp() {
Activity activity = activityWeakReference.get();
try {
changeState(State.OPENING);
connectionResult.startResolutionForResult(activity, REQUEST_CODE);
} catch (IntentSender.SendIntentException e) {
changeState(State.CREATED);
googleApiClient.connect();
}
}
protected void onRevoke() {
Plus.AccountApi.clearDefaultAccount(googleApiClient);
Plus.AccountApi.revokeAccessAndDisconnect(googleApiClient);
googleApiClient = googleApiClientBuilder.build();
googleApiClient.connect();
changeState(State.CLOSED);
}
2. Государственный паттерн
Это поведенческий паттерн, позволяющий объекту изменять свое поведение при изменении его внутреннего состояния. В книге GoF Design Patterns описывается, как TCP-соединение может быть представлено этим шаблоном (что также является нашим случаем).
Состояние из конечного автомата должно быть singleton
и проще всего сделать это на Java было создать Enum
названный State
следующее:
public enum State {
CREATED {
@Override
void connect(Connection connection) {
connection.onSignUp();
}
@Override
void disconnect(Connection connection) {
connection.onSignOut();
}
},
OPENING {},
OPENED {
@Override
void disconnect(Connection connection) {
connection.onSignOut();
}
@Override
void revoke(Connection connection) {
connection.onRevoke();
}
},
CLOSED {
@Override
void connect(Connection connection) {
connection.onSignIn();
}
};
void connect(Connection connection) {}
void disconnect(Connection connection) {}
void revoke(Connection connection) {}
Connection
класс содержит контекст, то есть текущее состояние, которое определяет, как Connection
методы connect
, disconnect
, а также revoke
будет вести себя
public void connect() {
currentState.connect(this);
}
public void disconnect() {
currentState.disconnect(this);
}
public void revoke() {
currentState.revoke(this);
}
private void changeState(State state) {
currentState = state;
setChanged();
notifyObservers(state);
}
3. Синглтон
Поскольку нет необходимости повторно создавать этот класс, мы предоставляем его как одиночный:
public static Connection getInstance(Activity activity) {
if (null == sConnection) {
sConnection = new Connection(activity);
}
return sConnection;
}
public void onActivityResult(int result) {
if (result == Activity.RESULT_OK) {
changeState(State.CREATED);
} else {
changeState(State.CLOSED);
}
onSignIn();
}
private Connection(Activity activity) {
activityWeakReference = new WeakReference<>(activity);
googleApiClientBuilder = new GoogleApiClient
.Builder(activity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, Plus.PlusOptions.builder().build())
.addScope(new Scope("email"));
googleApiClient = googleApiClientBuilder.build();
currentState = State.CLOSED;
}
4. Наблюдаемая картина
Connection
класс расширяет Java Observable
Таким образом, 1 или более действий могут наблюдать изменения состояния:
@Override
protected void onCreate(Bundle bundle) {
connection = Connection.getInstance(this);
connection.addObserver(this);
}
@Override
protected void onStart() {
connection.connect();
}
@Override
protected void onDestroy() {
connection.deleteObserver(this);
connection.disconnect();
}
@Override
protected void onActivityResult(int request, int result, Intent data) {
if (Connection.REQUEST_CODE == request) {
connection.onActivityResult(result);
}
}
@Override
public void update(Observable observable, Object data) {
if (observable != connection) {
return;
}
// Your presentation logic goes here...
}
Для любого, кто читает этот вопрос, вы также можете проверить этот ответ Иана Барбера, а также ответ ниже, на который ответил Ли, в котором объясняются три основных способа работы с Google плюс логин и несколько активаций, которые я считаю очень полезными на самом деле.