Cihaz Keşfi ve Güvenli Bağlantı API'lerini temel alan Sessions API, cihazlar arası sorunsuz derleme için güçlü bir soyutlama sağlıyor paylaşmaya istekli olmalıdır. Oturum, kullanıcı tarafından sunulan uygulama deneyimini temsil eder. aktarılıp paylaşılabilir.
Sessions API'de ayrıca kişisel ve sosyal Oturum aktarma ve oturum paylaşımı kullanım alanlarıyla temsil edilen deneyimler tıklayın. Aşağıdaki şemada oturumlar genel bir şekilde gösterilmektedir:

Oturum oluşturma ve aktarma
Sessions API, kaynak cihaz ile alıcı cihazı birbirinden ayırt eder. Kaynak cihaz, oturumu oluşturur ve kabul etmenizi sağlar. Kaynak cihazın kullanıcısı Kullanıcı, sistem iletişim kutusu tarafından sağlanan listeden bir cihaz seçer. Kullanıcı Alıcı cihazı seçtiğinde kaynak oturum aktarılır ve kaldırılır kaldırmamız gerekir.
Oturumu aktarmak için önce aşağıdakini kullanarak oluşturmanız gerekir: parametre:
- Uygulama oturumu etiketi: Diğer kullanıcıları ayırt etmenizi sağlayan bir tanımlayıcı oturum arasında dönüşüm elde edersiniz.
Ardından aşağıdaki parametreleri kullanarak aktarımı başlatın:
- Oturumu işleyebilen cihazları filtrelemek için
DeviceFilter
OriginatingSessionStateCallback
uygulayan bir geri çağırma nesnesi
Kaynak cihazda, aşağıdaki örneği kullanarak bir oturum oluşturun:
private val HELLO_WORLD_TRANSFER_ACTION = "hello_world_transfer"
private lateinit var originatingSession: OriginatingSession
private lateinit var sessions: Sessions
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sessions = Sessions.create(context = this)
}
suspend fun transferSession() {
val sessionId =
sessions.createSession(
ApplicationSessionTag("hello_world_transfer"),
)
originatingSession =
sessions.transferSession(
sessionId,
StartComponentRequest.Builder()
.setAction(HELLO_WORLD_TRANSFER_ACTION)
.setReason("Transfer reason here")
.build(),
emptyList(),
HelloWorldTransferSessionStateCallback()
)
}
private static final String HELLO_WORLD_TRANSFER_ACTION = "hello_world_transfer";
private OriginatingSession originatingSession;
private Sessions sessions;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessions = Sessions.create(/* context= */ this);
}
public void transferSession() {
SessionId sessionId = sessions.createSession(new ApplicationSessionTag("hello_world_transfer"));
ListenableFuture<OriginatingSession> originatingSessionFuture =
sessions.transferSessionFuture(
sessionId,
new StartComponentRequest.Builder()
.setAction(HELLO_WORLD_TRANSFER_ACTION)
.setReason("Transfer reason here")
.build(),
Collections.emptyList(),
new HelloWorldTransferSessionStateCallback());
Futures.addCallback(
originatingSessionFuture,
new FutureCallback<>() {
@Override
public void onSuccess(OriginatingSession result) {
// Do nothing, handled in HelloWorldTransferSessionStateCallback
originatingSession = result;
}
@Override
public void onFailure(Throwable t) {
Log.d(TAG, "onFailure called for transferSessionFuture", t);
}
},
mainExecutor);
}
Daha sonra, kaynak cihazda oturum geri çağırmasını tanımlayın:
private inner class HelloWorldTransferSessionStateCallback : OriginatingSessionStateCallback {
override fun onConnected(sessionId: SessionId) {
val startupRemoteConnection = originatingSession.getStartupRemoteConnection()
lifecycleScope.launchWhenResumed {
startupRemoteConnection.send("hello, world".toByteArray(UTF_8))
startupRemoteConnection.registerReceiver(
object : SessionConnectionReceiver {
override fun onMessageReceived(participant: SessionParticipant, payload: ByteArray) {
val ok = payload.contentEquals("ok".toByteArray(UTF_8))
Log.d(TAG, "Session transfer initialized. ok=$ok")
}
}
)
}
}
override fun onSessionTransferred(sessionId: SessionId) {
Log.d(TAG, "Transfer done.")
}
override fun onTransferFailure(sessionId: SessionId, exception: SessionException) {
// Handle error
}
}
private class HelloWorldTransferSessionStateCallback implements OriginatingSessionStateCallback {
@Override
public void onConnected(SessionId sessionId) {
SessionRemoteConnection startupRemoteConnection =
originatingSession.getStartupRemoteConnection();
Futures.addCallback(
startupRemoteConnection.sendFuture("hello, world".getBytes()),
new FutureCallback<>() {
@Override
public void onSuccess(Void result) {
Log.d(TAG, "Successfully sent initialization message");
}
@Override
public void onFailure(Throwable t) {
Log.d(TAG, "Failed to send initialization message", t);
}
},
mainExecutor);
}
@Override
public void onSessionTransferred(SessionId sessionId) {
Log.d(TAG, "Transfer done.");
}
@Override
public void onTransferFailure(SessionId sessionId, SessionException exception) {
// Handle error
}
}
Oturum aktarımı başlatıldıktan sonra, alıcı cihaz bir geri arama alır
onNewIntent(intent: Intent)
yöntemi. Amaç verileri her şeyi içerir
gerekli değildir.
Alıcı cihazda aktarımı tamamlamak için:
private lateinit var sessions: Sessions
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sessions = Sessions.create(context = this)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
lifecycleScope.launchWhenResumed {
val receivingSession =
sessions.getReceivingSession(intent, HelloWorldReceivingSessionStateCallback())
// Get info from receiving device and init.
val startupRemoteConnection = receivingSession.getStartupRemoteConnection()
startupRemoteConnection.registerReceiver(
object : SessionConnectionReceiver {
override fun onMessageReceived(participant: SessionParticipant, payload: ByteArray) {
lifecycleScope.launchWhenResumed {
val transferInfo = String(payload)
startupRemoteConnection.send("ok".toByteArray(UTF_8))
// Complete transfer.
Log.d(TAG, "Transfer info: " + transferInfo)
receivingSession.onComplete()
}
}
}
)
}
}
private inner class HelloWorldReceivingSessionStateCallback : ReceivingSessionStateCallback {
override fun onTransferFailure(sessionId: SessionId, exception: SessionException) {
// Handle error
}
}
private Sessions sessions;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessions = Sessions.create(/* context= */ this);
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
ListenableFuture<ReceivingSession> receivingSessionFuture =
sessions.getReceivingSessionFuture(intent, new HelloWorldReceivingSessionStateCallback());
ListenableFuture<Void> registerReceiverFuture =
Futures.transform(
receivingSessionFuture,
receivingSession -> {
SessionRemoteConnection startupRemoteConnection =
receivingSession.getStartupRemoteConnection();
SessionConnectionReceiver receiver =
(participant, payload) -> {
Log.d(
TAG,
"Successfully received initialization message of size: " + payload.length);
applicationInitialization(receivingSession, payload);
};
startupRemoteConnection.registerReceiver(receiver);
return null;
},
mainExecutor);
Futures.addCallback(
registerReceiverFuture,
new FutureCallback<Void>() {
@Override
public void onSuccess(Void unused) {
Log.d(TAG, "Connection receiver registerd successfully");
}
@Override
public void onFailure(Throwable t) {
Log.w(TAG, "Failed to register connection receiver", t);
}
},
mainExecutor);
}
private void applicationInitialization(ReceivingSession receivingSession, byte[] initMessage) {
ListenableFuture<SessionId> disconnectFuture =
Futures.transform(
receivingSession.onCompleteFuture(),
sessionId -> {
Log.d(TAG, "Succeeded to complete receive transfer for: " + sessionId);
return sessionId;
},
mainExecutor);
Futures.addCallback(
disconnectFuture,
new FutureCallback<SessionId>() {
@Override
public void onSuccess(SessionId result) {
Log.d(TAG, "Succeeded to remove the old session: " + result);
}
@Override
public void onFailure(Throwable t) {
Log.d(TAG, "Failed to remove the old session, which is now orphaned", t);
}
},
mainExecutor);
}
private static class HelloWorldReceivingSessionStateCallback
implements ReceivingSessionStateCallback {
@Override
public void onTransferFailure(SessionId sessionId, SessionException exception) {
// Handle error
}
}
Alıcı cihaz artık kullanıcı deneyimine devam edebilir.
Oturumları paylaşma
Oturum paylaşarak etrafınızdaki diğer kullanıcıları bir gruba katılmaya davet edebilirsiniz Örneğin:
- Harita konumunu doğrudan arkadaşınızın aracıyla yolcu olarak paylaşabilirsiniz.
- Pazar günü bisiklet rotanızı bisiklete bindiğiniz diğer kişilerle paylaşın.
- Telefonunuzu dağıtmadan grup yemek siparişi için öğe toplayın.
- Birlikte izlemek istediğiniz bir sonraki TV programı için grup oyu verin.
Bir kullanıcı, oturumu başka bir cihazla paylaşmayı seçtiğinde, oturuma katılabilen cihazları arar ve sunar. Kullanıcı, alıcı cihazları seçtiğinde. Uygulama, kullanıcıdan bir alıcı cihazın, kaynak cihazdan oturuma katılması için gereklidir. Alıcı oturumla etkileşimde bulunması için öncelikle cihazdaki kaynak cihaz. Uygulamalar ayrıca kendi devam eden bir paylaşılan oturum.
Oturumu paylaşma süreci, oturum aktarmaya benzer.
ancak transferSession
yerine shareSession
numaralı telefonu arayın. Diğer
farklılıklar oturum durumu geri çağırma yöntemlerindedir.
// Originating side.
private val HELLO_WORLD_SHARE_ACTION = "hello_world_share"
private var activePrimarySession: PrimarySession? = null
private lateinit var sessions: Sessions
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sessions = Sessions.create(context = this)
}
suspend fun shareSession() {
val sessionId = sessions.createSession(ApplicationSessionTag("hello_world_share"))
activePrimarySession =
sessions.shareSession(
sessionId,
StartComponentRequest.Builder()
.setAction(HELLO_WORLD_SHARE_ACTION)
.setReason("Share reason here")
.build(),
emptyList(),
HelloWorldShareSessionStateCallback(),
)
}
private inner class HelloWorldShareSessionStateCallback : PrimarySessionStateCallback {
override fun onShareInitiated(sessionId: SessionId, numPotentialParticipants: Int) {
// Custom logic here for when n devices can potentially join.
// e.g. if there were 0, cancel/error if desired,
// if non-0 maybe spin until numPotentialParticipants join etc.
}
override fun onParticipantJoined(sessionId: SessionId, participant: SessionParticipant) {
// Custom join logic here
lifecycleScope.launchWhenResumed {
// Example logic: send only to the participant who just joined.
val connection =
checkNotNull(activePrimarySession).getSecondaryRemoteConnectionForParticipant(participant)
connection.send("Initing hello, world.".toByteArray(UTF_8))
connection.registerReceiver(
object : SessionConnectionReceiver {
override fun onMessageReceived(participant: SessionParticipant, payload: ByteArray) {
val ok = payload.contentEquals("ok".toByteArray(UTF_8))
Log.d(TAG, "Session share initialized. ok=$ok")
// Example logic: broadcast to all participants, including the one
// that just joined.
lifecycleScope.launchWhenResumed {
checkNotNull(activePrimarySession)
.broadcastToSecondaries("hello, all.".toByteArray(UTF_8))
}
}
}
)
}
}
override fun onParticipantDeparted(sessionId: SessionId, participant: SessionParticipant) {
// Custom leave logic here.
}
override fun onPrimarySessionCleanup(sessionId: SessionId) {
// Custom cleanup logic here.
activePrimarySession = null
}
override fun onShareFailureWithParticipant(
sessionId: SessionId,
exception: SessionException,
participant: SessionParticipant
) {
// Handle error
}
}
// Originating side
private static final String HELLO_WORLD_SHARE_ACTION = "hello_world_share";
@Nullable private PrimarySession activePrimarySession = null;
private Sessions sessions;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sessions = Sessions.create(/* context= */ this);
}
private void shareSession() {
SessionId sessionId = sessions.createSession(new ApplicationSessionTag("hello_world_share"));
ListenableFuture<PrimarySession> shareSessionFuture =
sessions.shareSessionFuture(
sessionId,
new StartComponentRequest.Builder()
.setAction(HELLO_WORLD_SHARE_ACTION)
.setReason("Share reason here")
.build(),
Collections.emptyList(),
new HelloWorldShareSessionStateCallback());
Futures.addCallback(
shareSessionFuture,
new FutureCallback<PrimarySession>() {
@Override
public void onSuccess(PrimarySession primarySession) {
activePrimarySession = primarySession;
}
@Override
public void onFailure(Throwable t) {
Log.d(TAG, "Failed to share session", t);
}
},
mainExecutor);
}
private class HelloWorldShareSessionStateCallback implements PrimarySessionStateCallback {
@Override
public void onShareInitiated(SessionId sessionId, int numPotentialParticipants) {
// Custom logic here for when n devices can potentially join.
// e.g. if there were 0, cancel/error if desired,
// if non-0 maybe spin until numPotentialParticipants join etc.
}
@Override
public void onParticipantJoined(SessionId sessionId, SessionParticipant participant) {
PrimarySession joinedSession = activePrimarySession;
if (joinedSession == null) {
return;
}
SessionRemoteConnection connection =
joinedSession.getSecondaryRemoteConnectionForParticipant(participant);
Futures.addCallback(
connection.sendFuture("Initiating hello, world.".getBytes()),
new FutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
// Send successful.
}
@Override
public void onFailure(Throwable t) {
// Failed to send.
}
},
mainExecutor);
connection.registerReceiver(
new SessionConnectionReceiver() {
@Override
public void onMessageReceived(SessionParticipant participant, byte[] payload) {
boolean ok = new String(payload, UTF_8).equals("ok");
Log.d(TAG, "Session share initialized. ok=" + ok);
// Example logic: broadcast to all participants, including the one
// that just joined.
Futures.addCallback(
joinedSession.broadcastToSecondariesFuture("hello, all.".getBytes()),
new FutureCallback<Void>() {
@Override
public void onSuccess(Void result) {
// Broadcast successful.
}
@Override
public void onFailure(Throwable t) {
// Failed to broadcast hello world.
}
},
mainExecutor);
}
});
}
@Override
public void onParticipantDeparted(SessionId sessionId, SessionParticipant participant) {
// Custom leave logic here.
}
@Override
public void onPrimarySessionCleanup(SessionId sessionId) {
// Custom cleanup logic here.
activePrimarySession = null;
}
@Override
public void onShareFailureWithParticipant(
SessionId sessionId, SessionException exception, SessionParticipant participant) {
// Custom error handling logic here.
}
}
Alıcı tarafta:
// Receiving side.
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
lifecycleScope.launchWhenResumed {
val secondarySession =
sessions.getSecondarySession(intent, HelloWorldSecondaryShareSessionStateCallback())
val remoteConnection = secondarySession.getDefaultRemoteConnection()
remoteConnection.registerReceiver(
object : SessionConnectionReceiver {
override fun onMessageReceived(participant: SessionParticipant, payload: ByteArray) {
Log.d(TAG, "Payload received: ${String(payload)}")
}
}
)
}
}
private inner class HelloWorldSecondaryShareSessionStateCallback : SecondarySessionStateCallback {
override fun onSecondarySessionCleanup(sessionId: SessionId) {
// Custom cleanup logic here.
}
}
// Receiving side.
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
sessions = Sessions.create(this);
ListenableFuture<SecondarySession> secondarySessionFuture =
sessions.getSecondarySessionFuture(
intent, new HelloWorldSecondaryShareSessionStateCallback());
Futures.addCallback(
secondarySessionFuture,
new FutureCallback<SecondarySession>() {
@Override
public void onSuccess(SecondarySession secondarySession) {
SessionRemoteConnection remoteConnection =
secondarySession.getDefaultRemoteConnection();
remoteConnection.registerReceiver(
new SessionConnectionReceiver() {
@Override
public void onMessageReceived(SessionParticipant participant, byte[] payload) {
Log.d(TAG, "Payload received: " + new String(payload, UTF_8));
}
});
}
@Override
public void onFailure(Throwable t) {
// Handle error.
}
},
mainExecutor);
}
private static class HelloWorldSecondaryShareSessionStateCallback
implements SecondarySessionStateCallback {
@Override
public void onSecondarySessionCleanup(SessionId sessionId) {
// Custom cleanup logic here.
}
}