私はグーグルプラスを統合したアプリケーションを開発しています。これまでのところ正常に動作しているので、ユーザープロファイルを取得できます。
しかし今、私は次のことをしたいと思います:
1)2つのアクティビティsignInActivity
とshareActivity
があります。
2)ユーザーがすでにsignInActivity
を使用してサインインしている場合は、shareActivity
で再度サインインを要求せず、コンテンツを直接共有する必要があります。
3)ユーザーがsignInActivity
にサインインしておらず、shareActivity
を使用してデータを共有しようとした場合、アプリはユーザーにサインインしてから、データのみを共有する必要があります。この場合、ユーザーがsignInActivity
に戻ると、アプリは「すでにサインインしています」と表示するはずです。
要するに、ユーザーサインインをアプリケーション内でCentralにして、それがalradyサインインされている場合は、どのアクティビティからでもアクセスできるようにする必要があります。
アクセストークンについて聞いたことがありますが、使用方法がわかりません。ドキュメントには、1時間で期限切れになると記載されていますが、これは私が望んでいることではありません。
どうすれば中央のグーグルプラスサインインを作ることができますか?出来ますか?または、各アクティビティでユーザーを認証する必要がありますか?
各アクティビティでGoogleApiClientの個別のインスタンスを管理すると、notになり、ユーザーは複数回サインインするように求められます。
Google+サインイン(つまり、GoogleApiClient)は、デバイス上のGoogleアカウントとGooglePlay開発者サービスのコアサービスへのインターフェースを提供します。GoogleApiClientインスタンスごとの状態はありません。そのため、アプリのデバイスアカウントが認証されると、GoogleApiClientの新しいインスタンスが同じ状態にアクセスします。 GoogleApiClientは、GooglePlay開発者サービスによって管理されている中央の状態にアクセスするための軽量な方法となるように特別に設計されています。
アクセストークンに関しては幸運です! Google Play開発者サービスが、すべてのトークン管理を処理します。したがって、アクセストークンは1時間しか持続しませんが、おっしゃるように、PlusClientを使用してGoogle APIにアクセスしようとして、アクセストークンの有効期限が切れている場合、GooglePlay開発者サービスは透過的に新しいアクセストークンを要求して通話を完了します。
詳細については、このGoogle I/Oトークの最初の部分をご覧ください。
せっかちなコーダーの場合、次の実装の動作バージョンは GitHub にあります。これは別の Stack Overflow post に書かれた同じ答えです。
多くの異なるアプリでログインアクティビティコードを数回書き直した後、簡単な(そしてそれほどエレガントではない)ソリューションは、アプリケーションクラスオブジェクトとしてGoogleAPIクライアントを作成することでした。しかし、接続状態はUXフローに影響を与えるため、このアプローチには満足できませんでした。
問題を接続の概念だけに還元すると、次のように考えることができます。
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();
}
}
アクティビティは、メソッドconnect
、disconnect
、およびrevoke
を介してConnectionクラスと通信できますが、その動作は現在の状態によって決定されます。ステートマシンには次のメソッドが必要です。
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);
}
これは、内部状態が変化したときにオブジェクトがその動作を変更できるようにする動作パターンです。 GoF Design Patterns book は、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);
}
このクラスを繰り返し再作成する必要がないため、シングルトンとして提供します。
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;
}
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...
}
この質問を読んでいる人は誰でも Ian Barberによるこの回答を確認してください そしてLeeが回答した以下の質問もできます。実際に。