|
|
@ -15,11 +15,16 @@ import android.os.Looper |
|
|
import android.util.Log |
|
|
import android.util.Log |
|
|
import io.flutter.embedding.engine.FlutterEngineCache |
|
|
import io.flutter.embedding.engine.FlutterEngineCache |
|
|
import io.flutter.plugin.common.MethodChannel // 添加这行导入 |
|
|
import io.flutter.plugin.common.MethodChannel // 添加这行导入 |
|
|
|
|
|
import android.net.Uri |
|
|
|
|
|
import android.provider.OpenableColumns |
|
|
|
|
|
import java.io.File |
|
|
|
|
|
import java.io.FileOutputStream |
|
|
|
|
|
|
|
|
class MainActivity: FlutterActivity() { |
|
|
class MainActivity: FlutterActivity() { |
|
|
private val TAG = "MainActivity" |
|
|
private val TAG = "MainActivity" |
|
|
private var pendingDeepLink: Intent? = null |
|
|
private var pendingDeepLink: Intent? = null |
|
|
private var pendingNavigationIntent: Intent? = null |
|
|
private var pendingNavigationIntent: Intent? = null |
|
|
|
|
|
private var pendingShareIntent: Intent? = null |
|
|
|
|
|
|
|
|
private val EXTRA_NAVIGATE_TO = "com.saitong.voitrans.extra.NAVIGATE_TO" |
|
|
private val EXTRA_NAVIGATE_TO = "com.saitong.voitrans.extra.NAVIGATE_TO" |
|
|
private val NAVIGATE_TO_MEETING_RECORD = "meetingRecord" |
|
|
private val NAVIGATE_TO_MEETING_RECORD = "meetingRecord" |
|
|
@ -36,10 +41,20 @@ class MainActivity: FlutterActivity() { |
|
|
Log.d(TAG, "Intent extras: ${it.extras}") |
|
|
Log.d(TAG, "Intent extras: ${it.extras}") |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 暂存深链接,等Flutter引擎完全准备好后处理 |
|
|
intent?.let { |
|
|
if (intent?.action == Intent.ACTION_VIEW && intent?.data != null) { |
|
|
if (it.action == Intent.ACTION_SEND) { |
|
|
pendingDeepLink = intent |
|
|
pendingShareIntent = it |
|
|
Log.d(TAG, "🔗 暂存深链接,等待Flutter引擎准备完成") |
|
|
Log.d(TAG, "📎 暂存分享文件意图,等待Flutter引擎准备完成") |
|
|
|
|
|
} else if (it.action == Intent.ACTION_VIEW && it.data != null) { |
|
|
|
|
|
val uri = it.data |
|
|
|
|
|
if (uri != null && isLikelyAudio(it, uri)) { |
|
|
|
|
|
pendingShareIntent = it |
|
|
|
|
|
Log.d(TAG, "📎 暂存打开文件意图,等待Flutter引擎准备完成") |
|
|
|
|
|
} else { |
|
|
|
|
|
pendingDeepLink = it |
|
|
|
|
|
Log.d(TAG, "🔗 暂存深链接,等待Flutter引擎准备完成") |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (intent?.hasExtra(EXTRA_NAVIGATE_TO) == true) { |
|
|
if (intent?.hasExtra(EXTRA_NAVIGATE_TO) == true) { |
|
|
@ -110,6 +125,12 @@ class MainActivity: FlutterActivity() { |
|
|
|
|
|
|
|
|
// Flutter引擎配置完成后,处理待处理的深链接 |
|
|
// Flutter引擎配置完成后,处理待处理的深链接 |
|
|
Handler(Looper.getMainLooper()).postDelayed({ |
|
|
Handler(Looper.getMainLooper()).postDelayed({ |
|
|
|
|
|
pendingShareIntent?.let { intent -> |
|
|
|
|
|
Log.d(TAG, "📎 处理待处理的分享/打开文件意图") |
|
|
|
|
|
handleNavigationIntent(intent) |
|
|
|
|
|
pendingShareIntent = null |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
pendingDeepLink?.let { intent -> |
|
|
pendingDeepLink?.let { intent -> |
|
|
Log.d(TAG, "🔗 处理待处理的深链接") |
|
|
Log.d(TAG, "🔗 处理待处理的深链接") |
|
|
handleNavigationIntent(intent) |
|
|
handleNavigationIntent(intent) |
|
|
@ -135,6 +156,21 @@ class MainActivity: FlutterActivity() { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (it.action == Intent.ACTION_SEND || it.action == Intent.ACTION_VIEW) { |
|
|
|
|
|
try { |
|
|
|
|
|
val path = extractAudioPathFromIntent(it) |
|
|
|
|
|
if (path != null) { |
|
|
|
|
|
flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger -> |
|
|
|
|
|
val channel = MethodChannel(messenger, "com.saitong.voitrans/deeplink") |
|
|
|
|
|
channel.invokeMethod("handleSharedFile", mapOf("filePath" to path)) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "❌ 处理分享/打开文件失败", e) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (it.action == Intent.ACTION_VIEW && it.data != null) { |
|
|
if (it.action == Intent.ACTION_VIEW && it.data != null) { |
|
|
val uri = it.data |
|
|
val uri = it.data |
|
|
Log.d(TAG, "🔗 处理深链接: $uri") |
|
|
Log.d(TAG, "🔗 处理深链接: $uri") |
|
|
@ -169,6 +205,65 @@ class MainActivity: FlutterActivity() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun extractAudioPathFromIntent(intent: Intent): String? { |
|
|
|
|
|
val uri: Uri? = when (intent.action) { |
|
|
|
|
|
Intent.ACTION_SEND -> intent.getParcelableExtra(Intent.EXTRA_STREAM) |
|
|
|
|
|
Intent.ACTION_VIEW -> intent.data |
|
|
|
|
|
else -> null |
|
|
|
|
|
} |
|
|
|
|
|
if (uri == null) return null |
|
|
|
|
|
if (!isLikelyAudio(intent, uri)) return null |
|
|
|
|
|
return copyUriToCache(uri) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun isLikelyAudio(intent: Intent, uri: Uri): Boolean { |
|
|
|
|
|
val type = intent.type ?: "" |
|
|
|
|
|
if (type.startsWith("audio/")) return true |
|
|
|
|
|
val scheme = uri.scheme ?: "" |
|
|
|
|
|
if (scheme == "content" || scheme == "file") return true |
|
|
|
|
|
val path = uri.toString().lowercase() |
|
|
|
|
|
return path.endsWith(".wav") || path.endsWith(".mp3") || path.endsWith(".m4a") || path.endsWith(".aac") |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun copyUriToCache(uri: Uri): String? { |
|
|
|
|
|
return try { |
|
|
|
|
|
val resolver = applicationContext.contentResolver |
|
|
|
|
|
val cursor = resolver.query(uri, null, null, null, null) |
|
|
|
|
|
var displayName = "shared_audio" |
|
|
|
|
|
cursor?.use { |
|
|
|
|
|
val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME) |
|
|
|
|
|
if (nameIndex >= 0 && it.moveToFirst()) { |
|
|
|
|
|
displayName = it.getString(nameIndex) ?: displayName |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
val ext = when { |
|
|
|
|
|
displayName.endsWith(".wav", true) -> "wav" |
|
|
|
|
|
displayName.endsWith(".mp3", true) -> "mp3" |
|
|
|
|
|
displayName.endsWith(".m4a", true) -> "m4a" |
|
|
|
|
|
displayName.endsWith(".aac", true) -> "aac" |
|
|
|
|
|
else -> displayName.substringAfterLast('.', "audio") |
|
|
|
|
|
} |
|
|
|
|
|
val sharedDir = File(applicationContext.filesDir, "shared_audio") |
|
|
|
|
|
if (!sharedDir.exists()) sharedDir.mkdirs() |
|
|
|
|
|
val outFile = File(sharedDir, "audio_${System.currentTimeMillis()}.$ext") |
|
|
|
|
|
resolver.openInputStream(uri)?.use { inStream -> |
|
|
|
|
|
FileOutputStream(outFile).use { out -> |
|
|
|
|
|
val buffer = ByteArray(8192) |
|
|
|
|
|
var len: Int |
|
|
|
|
|
while (true) { |
|
|
|
|
|
len = inStream.read(buffer) |
|
|
|
|
|
if (len <= 0) break |
|
|
|
|
|
out.write(buffer, 0, len) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
outFile.absolutePath |
|
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
|
Log.e(TAG, "复制分享文件到缓存失败: ${e.message}", e) |
|
|
|
|
|
null |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private fun pushRouteToFlutter(route: String) { |
|
|
private fun pushRouteToFlutter(route: String) { |
|
|
try { |
|
|
try { |
|
|
val engine = flutterEngine |
|
|
val engine = flutterEngine |
|
|
|