Skip to content
This repository has been archived by the owner on Sep 17, 2020. It is now read-only.

Commit

Permalink
P2P通信でデータ交換してsqliteに保存まで
Browse files Browse the repository at this point in the history
  • Loading branch information
okwrtdsh committed Oct 19, 2019
1 parent dfd3d9e commit 00ec694
Show file tree
Hide file tree
Showing 10 changed files with 453 additions and 94 deletions.
9 changes: 9 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,13 @@ dependencies {
implementation 'com.amazonaws:aws-android-sdk-appsync:2.8.3'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'


// NearBy
implementation 'com.google.android.gms:play-services-nearby:17.0.0'


// Gson
implementation 'com.google.code.gson:gson:2.8.6'

}
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand Down
301 changes: 286 additions & 15 deletions app/src/main/java/com/github/okwrtdsh/idobatter/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import com.github.okwrtdsh.idobatter.room.Message
import com.github.okwrtdsh.idobatter.room.MessageViewModel
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.nearby.Nearby
import com.google.android.gms.nearby.connection.*
import kotlinx.android.synthetic.main.activity_main.*
import type.CreateCoordinateInput
import java.text.SimpleDateFormat
Expand All @@ -51,7 +53,7 @@ class MessageListAdapter internal constructor(

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageViewHolder {
val itemView = inflater.inflate(R.layout.recyclerview_item, parent, false)
return MessageViewHolder(itemView)
return MessageViewHolder(itemView) // TODO: onclicklistener
}

override fun onBindViewHolder(holder: MessageViewHolder, position: Int) {
Expand All @@ -78,14 +80,20 @@ class MainActivity : AppCompatActivity() {
private lateinit var cm: ConnectivityManager
private var isConnected = false
private lateinit var mAWSAppSyncClient: AWSAppSyncClient
private var isActive: Boolean = false
private lateinit var mConnectionsClient: ConnectionsClient
private var mRemoteEndpointId: String? = null
private var mRemoteClientStatus: Int = STATUS_READY
private var mMyClientStatus: Int = STATUS_READY


companion object {
private const val REQUEST_CODE_PERMISSIONS = 1
// private const val TAG: String = "idobatter"
// private const val channelId = "com.github.okwrtdsh.idobatter"
// private const val channelDescription = "Description"
// private const val channelName = "idobatter"
private const val TAG: String = "idobatter"
private const val SERVICE_ID: String = "com.github.okwrtdsh.idobatter"
private const val STATUS_DONE = 1
private const val STATUS_IN_PROGRESS = 2
private const val STATUS_READY = 3
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -104,6 +112,20 @@ class MainActivity : AppCompatActivity() {
val intent = Intent(this@MainActivity, NewMessageActivity::class.java)
startActivityForResult(intent, newMessageActivityRequestCode)
}
onOff.setOnCheckedChangeListener { _, isChecked ->
isActive = isChecked
if (isActive) {
startAdvertising()
startDiscovery()
}
else {
stopAdvertising()
stopDiscovery()
mConnectionsClient.stopAllEndpoints()
disconnectFromEndpoint()
}
}
mConnectionsClient = Nearby.getConnectionsClient(this)

// amplify
mAWSAppSyncClient = AWSAppSyncClient.builder()
Expand Down Expand Up @@ -135,10 +157,15 @@ class MainActivity : AppCompatActivity() {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == newMessageActivityRequestCode && resultCode == Activity.RESULT_OK) {
data?.let {
messageViewModel.create(
it.getStringExtra(NewMessageActivity.EXTRA_REPLY),
fusedLocationClient=fusedLocationClient
)
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
messageViewModel.create(
it.getStringExtra(NewMessageActivity.EXTRA_REPLY),
current_lat = location.latitude,
current_lng = location.longitude
)
}
}
}
}
else {
Expand Down Expand Up @@ -173,8 +200,7 @@ class MainActivity : AppCompatActivity() {
private fun uploadCoordinateData() {
if (isConnected) {
val mutation = CreateCoordinateMutation.builder()
messageViewModel.uploadable().map { message ->
Log.d("#########", message.content)
if (messageViewModel.uploadable().map { message ->
mutation.input(
CreateCoordinateInput.builder()
.uuid(message.uuid)
Expand All @@ -183,11 +209,9 @@ class MainActivity : AppCompatActivity() {
.time(message.created.toInt())
.build()
)
Log.d("#########2", message.content)
message.isUploaded = true
messageViewModel.update(message.uuid)
}
runMutate(mutation.build())
}.isNotEmpty()) runMutate(mutation.build())
}

}
Expand All @@ -204,4 +228,251 @@ class MainActivity : AppCompatActivity() {
Log.e("Error", e.toString())
}
}
}


override fun onStop() {
super.onStop()
mConnectionsClient.stopAdvertising()
mConnectionsClient.stopDiscovery()
mConnectionsClient.stopAllEndpoints()
}

private fun startAdvertising() {
mConnectionsClient.startAdvertising(
getNickName(),
SERVICE_ID,
mConnectionLifecycleCallback,
AdvertisingOptions(Strategy.P2P_CLUSTER)
)
.addOnSuccessListener {
debug("Success startAdvertising: $it")
}
.addOnFailureListener {
debug("Failure startDiscovery: $it")
}
}

private fun stopAdvertising() {
mConnectionsClient.stopAdvertising()
debug("Success stopAdvertising")
}

private fun startDiscovery() {
mConnectionsClient.startDiscovery(
packageName,
mEndpointDiscoveryCallback,
DiscoveryOptions(Strategy.P2P_CLUSTER)
)
.addOnSuccessListener {
debug("Success startDiscovery: $it")
}
.addOnFailureListener {
debug("Failure startDiscovery: $it")
}
}

private fun stopDiscovery() {
mConnectionsClient.stopDiscovery()
debug("Success stopDiscovery")
}

private fun sendString(content: String) =
mConnectionsClient.sendPayload(
mRemoteEndpointId!!,
Payload.fromBytes(content.toByteArray(Charsets.UTF_8))
)

private fun disconnectFromEndpoint() {
if (mRemoteEndpointId != null) {
mConnectionsClient.disconnectFromEndpoint(mRemoteEndpointId!!)
mRemoteEndpointId = null
mRemoteClientStatus = STATUS_READY
mMyClientStatus = STATUS_READY
}
}

private val mEndpointDiscoveryCallback = object : EndpointDiscoveryCallback() {

override fun onEndpointFound(endpointId: String, info: DiscoveredEndpointInfo) {
// An endpoint was found. We request a connection to it.
debug("mEndpointDiscoveryCallback.onEndpointFound $endpointId:$info:${info.endpointName}")

mConnectionsClient.requestConnection(
getNickName(),
endpointId,
mConnectionLifecycleCallback
)
.addOnSuccessListener {
// We successfully requested a connection. Now both sides
// must accept before the connection is established.
debug("Success requestConnection: $it")
}
.addOnFailureListener {
// Nearby Connections failed to request the connection.
// TODO: retry
debug("Failure requestConnection: $it")
}
}

override fun onEndpointLost(endpointId: String) {
// A previously discovered endpoint has gone away.
debug("mEndpointDiscoveryCallback.onEndpointLost $endpointId")
}
}

private val mConnectionLifecycleCallback = object : ConnectionLifecycleCallback() {

override fun onConnectionInitiated(endpointId: String, connectionInfo: ConnectionInfo) {
debug("mConnectionLifecycleCallback.onConnectionInitiated $endpointId:${connectionInfo.endpointName}")

// Automatically accept the connection on both sides.
mConnectionsClient.acceptConnection(endpointId, mPayloadCallback)
}

override fun onConnectionResult(endpointId: String, result: ConnectionResolution) {
debug("mConnectionLifecycleCallback.onConnectionResult $endpointId")

when (result.status.statusCode) {
ConnectionsStatusCodes.STATUS_OK -> {
debug("onnectionsStatusCodes.STATUS_OK $endpointId")
// We're connected! Can now start sending and receiving data.
mRemoteEndpointId = endpointId

mMyClientStatus = STATUS_IN_PROGRESS
mRemoteClientStatus = STATUS_IN_PROGRESS

fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
Log.d("onConnectionResult.addOnSuccessListener",
"${location.latitude}, ${location.longitude}")
messageViewModel.enabled { messages ->
sendString(
P2PData(
"MSG",
messages.toGsonString()
).toGsonString()
)
sendString(P2PData("FIN", "").toGsonString())
mMyClientStatus = STATUS_DONE
}

}
else {
Log.d("onConnectionResult.addOnSuccessListener", "no GPS")
}
}
.addOnFailureListener {
Log.d("onConnectionResult.addOnFailureListener", it.toString())
}
.addOnCanceledListener {
Log.d("onConnectionResult.addOnCanceledListener", "Canceled")
}
}

ConnectionsStatusCodes.STATUS_CONNECTION_REJECTED -> {
// The connection was rejected by one or both sides.
debug("onnectionsStatusCodes.STATUS_CONNECTION_REJECTED $endpointId")
}

ConnectionsStatusCodes.STATUS_ERROR -> {
// The connection broke before it was able to be accepted.
debug("onnectionsStatusCodes.STATUS_ERROR $endpointId")
}
}
}

override fun onDisconnected(endpointId: String) {
// We've been disconnected from this endpoint. No more data can be
// sent or received.
debug("mConnectionLifecycleCallback.onDisconnected $endpointId")
disconnectFromEndpoint()
}

}


private val mPayloadCallback = object : PayloadCallback() {
override fun onPayloadReceived(endpointId: String, payload: Payload) {
debug("mPayloadCallback.onPayloadReceived $endpointId")

when (payload.type) {
Payload.Type.BYTES -> {
val data = payload.asBytes()!!
debug("Payload.Type.BYTES: ${data.toString(Charsets.UTF_8)}")

fusedLocationClient.lastLocation.addOnSuccessListener { location ->
if (location != null) {
communicationHandler(
data.toString(Charsets.UTF_8).toP2PData(),
location.latitude, location.longitude)

}
else {
Log.d("onConnectionResult.addOnSuccessListener", "no GPS")
}
}
.addOnFailureListener {
Log.d("onConnectionResult.addOnFailureListener", it.toString())
}
.addOnCanceledListener {
Log.d("onConnectionResult.addOnCanceledListener", "Canceled")
}

}
Payload.Type.FILE -> {
val file = payload.asFile()!!
debug("Payload.Type.FILE: size: ${file.size}")
// TODO:

}
Payload.Type.STREAM -> {
val stream = payload.asStream()!!
debug("Payload.Type.STREAM")
// TODO:
}
}
}

override fun onPayloadTransferUpdate(endpointId: String, update: PayloadTransferUpdate) {
// debug("mPayloadCallback.onPayloadTransferUpdate $endpointId")
}
}

private fun communicationHandler(data: P2PData, current_lat: Double?, current_lng: Double?) {
when(data.type) {
"MSG" -> {
data.body.toMessagesGson().messages.map {
messageViewModel.create(
it.content,
it.hops + 1,
false,
false,
false,
it.limitDist,
it.limitHops,
it.limitTime,
current_lat!!,
current_lng!!
)
}
}
"FIN" -> {
mRemoteClientStatus = STATUS_DONE
if (mMyClientStatus == STATUS_DONE) {
sendString(P2PData("ACK", "").toGsonString())
disconnectFromEndpoint()
}
}
"ACK" -> {
disconnectFromEndpoint()
}
}
}


private fun debug(message: String) {
Log.d(TAG, message)
}

private fun getNickName() = UUID.randomUUID().toString()
}
Loading

0 comments on commit 00ec694

Please sign in to comment.