Skip to content

Commit ce8b21d

Browse files
author
tanpengcheng
committed
[feat] Support handle other apps share request.
1 parent c864c00 commit ce8b21d

File tree

9 files changed

+471
-46
lines changed

9 files changed

+471
-46
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@
5252
<action android:name="android.intent.action.MAIN" />
5353
<category android:name="android.intent.category.LAUNCHER" />
5454
</intent-filter>
55+
<intent-filter>
56+
<action android:name="android.intent.action.SEND" />
57+
<category android:name="android.intent.category.DEFAULT" />
58+
<data android:mimeType="*/*" />
59+
</intent-filter>
60+
<intent-filter>
61+
<action android:name="android.intent.action.SEND_MULTIPLE" />
62+
<category android:name="android.intent.category.DEFAULT" />
63+
<data android:mimeType="*/*" />
64+
</intent-filter>
5565
</activity>
5666

5767
<activity android:name=".ui.filetransport.FileTransportActivity"

app/src/main/java/com/tans/tfiletransporter/ui/connection/ConnectionActivity.kt

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.Manifest
44
import android.content.Intent
55
import android.net.*
66
import android.os.Build
7+
import android.os.Bundle
78
import android.os.Environment
89
import android.provider.Settings
910
import android.view.View
@@ -18,15 +19,18 @@ import com.tans.tfiletransporter.ui.commomdialog.showOptionalDialogSuspend
1819
import com.tans.tfiletransporter.ui.commomdialog.showSettingsDialog
1920
import com.tans.tfiletransporter.ui.connection.localconnetion.LocalNetworkConnectionFragment
2021
import com.tans.tfiletransporter.ui.connection.wifip2pconnection.WifiP2pConnectionFragment
22+
import com.tans.tfiletransporter.utils.uri2FileReal
2123
import com.tans.tuiutils.activity.BaseCoroutineStateActivity
2224
import com.tans.tuiutils.permission.permissionsRequestSuspend
2325
import com.tans.tuiutils.systembar.annotation.SystemBarStyle
26+
import com.tans.tuiutils.view.clicks
2427
import kotlinx.coroutines.launch
2528
import kotlinx.coroutines.CoroutineScope
29+
import java.io.File
2630

2731
@SystemBarStyle(statusBarThemeStyle = 1, navigationBarThemeStyle = 1)
28-
class ConnectionActivity : BaseCoroutineStateActivity<Unit>(
29-
defaultState = Unit
32+
class ConnectionActivity : BaseCoroutineStateActivity<ConnectionActivity.Companion.ConnectionActivityState>(
33+
defaultState = ConnectionActivityState()
3034
) {
3135
override val layoutId: Int = R.layout.connection_activity
3236

@@ -38,6 +42,11 @@ class ConnectionActivity : BaseCoroutineStateActivity<Unit>(
3842
LocalNetworkConnectionFragment()
3943
}
4044

45+
override fun onCreate(savedInstanceState: Bundle?) {
46+
super.onCreate(savedInstanceState)
47+
checkIntentAction(intent)
48+
}
49+
4150
override fun CoroutineScope.firstLaunchInitDataCoroutine() {
4251
onBackPressedDispatcher.addCallback {
4352
finish()
@@ -119,12 +128,84 @@ class ConnectionActivity : BaseCoroutineStateActivity<Unit>(
119128
v.setPadding(0, 0, 0, systemBars.bottom)
120129
insets
121130
}
131+
132+
renderStateNewCoroutine({ it.requestShareFiles }) { requestShareFiles ->
133+
if (requestShareFiles.isNotEmpty()) {
134+
viewBinding.requestShareLayout.visibility = View.VISIBLE
135+
viewBinding.requestShareTv.text = getString(R.string.request_share_files, requestShareFiles.size)
136+
} else {
137+
viewBinding.requestShareLayout.visibility = View.GONE
138+
}
139+
}
140+
viewBinding.dropRequestShareBt.clicks(this) {
141+
updateState { it.copy(requestShareFiles = emptyList()) }
142+
}
143+
}
144+
145+
override fun onNewIntent(intent: Intent) {
146+
super.onNewIntent(intent)
147+
checkIntentAction(intent)
148+
}
149+
150+
fun consumeRequestShareFiles(): List<String> {
151+
val files = currentState().requestShareFiles
152+
if (files.isNotEmpty()) {
153+
updateState { it.copy(requestShareFiles = emptyList()) }
154+
}
155+
return files.map { it.canonicalPath }
156+
}
157+
158+
@Suppress("DEPRECATION")
159+
private fun checkIntentAction(intent: Intent) {
160+
if (intent.action == Intent.ACTION_SEND) {
161+
val uri: Uri? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
162+
intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM, Uri::class.java)
163+
} else {
164+
intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
165+
}
166+
AndroidLog.d(TAG, "Receive ACTION_SEND uri: $uri")
167+
if (uri != null) {
168+
handleSharedUris(listOf(uri))
169+
}
170+
}
171+
if (intent.action == Intent.ACTION_SEND_MULTIPLE) {
172+
val uris = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
173+
intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java) ?: emptyList<Uri>()
174+
} else {
175+
intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)?.mapNotNull { it } ?: emptyList<Uri>()
176+
}
177+
AndroidLog.d(TAG, "Receive ACTION_SEND_MULTIPLE uris: ${uris.joinToString { it.toString() }}")
178+
if (uris.isNotEmpty()) {
179+
handleSharedUris(uris)
180+
}
181+
}
182+
}
183+
184+
private fun handleSharedUris(uris: List<Uri>) {
185+
val files = uris.mapNotNull {
186+
val f = uri2FileReal(this@ConnectionActivity, it)
187+
if (f?.isFile == true && f.canRead() && f.length() > 0L) {
188+
f
189+
} else {
190+
null
191+
}
192+
}
193+
AndroidLog.d(TAG, "Handle shared files: $files")
194+
if (files.isNotEmpty()) {
195+
updateState {
196+
it.copy(requestShareFiles = files)
197+
}
198+
}
122199
}
123200

124201
companion object {
125202
private const val TAG = "ConnectionActivity"
126203

127204
private const val WIFI_P2P_CONNECTION_FRAGMENT_TAG = "WIFI_P2P_CONNECTION_FRAGMENT_TAG"
128205
private const val LOCAL_NETWORK_FRAGMENT_TAG = "LOCAL_NETWORK_FRAGMENT_TAG"
206+
207+
data class ConnectionActivityState(
208+
val requestShareFiles: List<File> = emptyList()
209+
)
129210
}
130211
}

app/src/main/java/com/tans/tfiletransporter/ui/connection/localconnetion/LocalNetworkConnectionFragment.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import java.net.InetAddress
3030
import java.util.Optional
3131
import kotlin.jvm.optionals.getOrNull
3232
import androidx.core.content.getSystemService
33+
import com.tans.tfiletransporter.ui.connection.ConnectionActivity
3334
import com.tans.tuiutils.actresult.startActivityResultSuspend
3435
import com.tans.tuiutils.adapter.impl.builders.SimpleAdapterBuilderImpl
3536
import com.tans.tuiutils.adapter.impl.databinders.DataBinderImpl
@@ -161,7 +162,8 @@ class LocalNetworkConnectionFragment : BaseCoroutineStateFragment<LocalNetworkCo
161162
localAddress = selectedAddress,
162163
remoteAddress = serverAddress,
163164
remoteDeviceInfo = qrcodeShare.deviceName,
164-
isServer = false
165+
isServer = false,
166+
requestShareFiles = (requireActivity() as ConnectionActivity).consumeRequestShareFiles()
165167
))
166168
}
167169
}.onFailure {
@@ -187,7 +189,8 @@ class LocalNetworkConnectionFragment : BaseCoroutineStateFragment<LocalNetworkCo
187189
localAddress = selectedAddress,
188190
remoteAddress = remoteAddress.remoteAddress.address,
189191
remoteDeviceInfo = remoteAddress.deviceName,
190-
isServer = true
192+
isServer = true,
193+
requestShareFiles = (requireActivity() as ConnectionActivity).consumeRequestShareFiles()
191194
))
192195
}
193196
}
@@ -208,7 +211,8 @@ class LocalNetworkConnectionFragment : BaseCoroutineStateFragment<LocalNetworkCo
208211
localAddress = selectedAddress,
209212
remoteAddress = remoteDevice.remoteAddress.address,
210213
remoteDeviceInfo = remoteDevice.deviceName,
211-
isServer = false
214+
isServer = false,
215+
requestShareFiles = (requireActivity() as ConnectionActivity).consumeRequestShareFiles()
212216
)
213217
)
214218
}
@@ -231,7 +235,8 @@ class LocalNetworkConnectionFragment : BaseCoroutineStateFragment<LocalNetworkCo
231235
localAddress = selectedAddress,
232236
remoteAddress = remoteDevice.remoteAddress.address,
233237
remoteDeviceInfo = remoteDevice.deviceName,
234-
isServer = true
238+
isServer = true,
239+
requestShareFiles = (requireActivity() as ConnectionActivity).consumeRequestShareFiles()
235240
))
236241
}
237242
}

app/src/main/java/com/tans/tfiletransporter/ui/connection/wifip2pconnection/WifiP2pConnectionFragment.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.tans.tfiletransporter.transferproto.p2pconn.connectSuspend
2424
import com.tans.tfiletransporter.transferproto.p2pconn.transferFileSuspend
2525
import com.tans.tfiletransporter.transferproto.p2pconn.waitClose
2626
import com.tans.tfiletransporter.transferproto.p2pconn.waitHandshaking
27+
import com.tans.tfiletransporter.ui.connection.ConnectionActivity
2728
import com.tans.tfiletransporter.ui.filetransport.FileTransportActivity
2829
import com.tans.tuiutils.adapter.impl.builders.SimpleAdapterBuilderImpl
2930
import com.tans.tuiutils.adapter.impl.databinders.DataBinderImpl
@@ -249,7 +250,8 @@ class WifiP2pConnectionFragment : BaseCoroutineStateFragment<WifiP2pConnectionFr
249250
localAddress = handshake.localAddress.address,
250251
remoteAddress = handshake.remoteAddress.address,
251252
remoteDeviceInfo = handshake.remoteDeviceName,
252-
isServer = isReceiver
253+
isServer = isReceiver,
254+
requestShareFiles = (requireActivity() as ConnectionActivity).consumeRequestShareFiles()
253255
)
254256
)
255257
}

app/src/main/java/com/tans/tfiletransporter/ui/filetransport/FileTransportActivity.kt

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ import com.tans.tfiletransporter.transferproto.fileexplore.waitClose
3232
import com.tans.tfiletransporter.transferproto.fileexplore.waitHandshake
3333
import com.tans.tfiletransporter.file.scanChildren
3434
import com.tans.tfiletransporter.transferproto.fileexplore.model.FileExploreFile
35+
import com.tans.tfiletransporter.transferproto.fileexplore.requestSendFilesSuspend
3536
import com.tans.tfiletransporter.transferproto.filetransfer.model.SenderFile
3637
import com.tans.tfiletransporter.ui.commomdialog.loadingDialogSuspend
3738
import com.tans.tfiletransporter.ui.commomdialog.showNoOptionalDialogSuspend
39+
import com.tans.tfiletransporter.ui.commomdialog.showOptionalDialogSuspend
3840
import com.tans.tfiletransporter.ui.commomdialog.showSettingsDialog
39-
import com.tans.tfiletransporter.utils.dp2px
41+
import com.tans.tfiletransporter.ui.filetransport.MyDirFragment.Companion
4042
import com.tans.tuiutils.activity.BaseCoroutineStateActivity
4143
import com.tans.tuiutils.systembar.annotation.SystemBarStyle
4244
import com.tans.tuiutils.view.clicks
@@ -56,6 +58,7 @@ import kotlinx.coroutines.withTimeout
5658
import java.net.InetAddress
5759
import java.io.File
5860
import java.lang.ref.WeakReference
61+
import java.util.ArrayList
5962
import java.util.concurrent.atomic.AtomicReference
6063
import kotlin.math.min
6164

@@ -346,6 +349,42 @@ class FileTransportActivity : BaseCoroutineStateActivity<FileTransportActivity.C
346349
floatActionBtnClickEvent.emit(Unit)
347350
}
348351
}
352+
353+
launch {
354+
stateFlow().map { it.connectionStatus }.first { it is ConnectionStatus.Connected }
355+
val requestShareFiles = intent.getRequestShareFiles()
356+
if (requestShareFiles.isNotEmpty()) {
357+
val share = supportFragmentManager.showOptionalDialogSuspend(
358+
title = getString(R.string.request_share_title),
359+
message = getString(R.string.request_share_body, requestShareFiles.size),
360+
positiveButtonText = getString(R.string.request_share_positive),
361+
negativeButtonText = getString(R.string.request_share_negative)
362+
)
363+
if (share == true) {
364+
val exploreFiles = requestShareFiles.map {
365+
val f = File(it)
366+
FileExploreFile(
367+
name = f.name,
368+
path = f.path,
369+
size = f.length(),
370+
lastModify = f.lastModified()
371+
)
372+
}
373+
runCatching {
374+
withContext(Dispatchers.IO) {
375+
fileExplore.requestSendFilesSuspend(exploreFiles, Settings.transferFileMaxConnection())
376+
}
377+
}.onSuccess {
378+
AndroidLog.d(TAG, "Request send files success: $it")
379+
runCatching {
380+
sendFiles(exploreFiles)
381+
}
382+
}.onFailure {
383+
AndroidLog.e(TAG, "Request send files fail: $it", it)
384+
}
385+
}
386+
}
387+
}
349388
}
350389

351390
fun observeFloatBtnClick(): Flow<Unit> = floatActionBtnClickEvent
@@ -426,6 +465,7 @@ class FileTransportActivity : BaseCoroutineStateActivity<FileTransportActivity.C
426465
private const val REMOTE_ADDRESS_EXTRA_KEY = "remote_address_extra_key"
427466
private const val REMOTE_INFO_EXTRA_KEY = "remote_info_extra_key"
428467
private const val IS_SERVER_EXTRA_KEY = "is_server_extra_key"
468+
private const val REQUEST_SHARE_FILES = "request_share_files_key"
429469

430470
@Suppress("DEPRECATION")
431471
private fun Intent.getLocalAddress(): InetAddress = getSerializableExtra(
@@ -441,6 +481,8 @@ class FileTransportActivity : BaseCoroutineStateActivity<FileTransportActivity.C
441481

442482
private fun Intent.getIsServer(): Boolean = getBooleanExtra(IS_SERVER_EXTRA_KEY, false)
443483

484+
private fun Intent.getRequestShareFiles(): List<String> = getStringArrayListExtra(REQUEST_SHARE_FILES) ?: emptyList()
485+
444486
data class Message(
445487
val time: Long,
446488
val msg: String,
@@ -475,12 +517,14 @@ class FileTransportActivity : BaseCoroutineStateActivity<FileTransportActivity.C
475517
localAddress: InetAddress,
476518
remoteAddress: InetAddress,
477519
remoteDeviceInfo: String,
478-
isServer: Boolean): Intent {
520+
isServer: Boolean,
521+
requestShareFiles: List<String>): Intent {
479522
val i = Intent(context, FileTransportActivity::class.java)
480523
i.putExtra(LOCAL_ADDRESS_EXTRA_KEY, localAddress)
481524
i.putExtra(REMOTE_ADDRESS_EXTRA_KEY, remoteAddress)
482525
i.putExtra(REMOTE_INFO_EXTRA_KEY, remoteDeviceInfo)
483526
i.putExtra(IS_SERVER_EXTRA_KEY, isServer)
527+
i.putStringArrayListExtra(REQUEST_SHARE_FILES, requestShareFiles as? ArrayList<String>)
484528
return i
485529
}
486530
}

0 commit comments

Comments
 (0)