Added deep link to multiplayer games (#6273)

This commit is contained in:
Leonard Günther
2022-03-05 19:00:56 +01:00
committed by GitHub
parent 1b9e496db5
commit 0e26ea2cc8
4 changed files with 87 additions and 33 deletions

View File

@ -29,9 +29,18 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true" >
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:scheme="https"
android:host="unciv.app"
android:path="/multiplayer"
/>
</intent-filter>
</activity>
<activity
android:name="com.unciv.app.AndroidTvLauncher"
android:label="@string/app_name"

View File

@ -2,7 +2,7 @@ package com.unciv.app
import android.content.Intent
import android.content.pm.ActivityInfo
import android.os.Build
import android.net.Uri
import android.os.Bundle
import androidx.core.app.NotificationManagerCompat
import androidx.work.WorkManager
@ -16,19 +16,16 @@ import java.io.File
open class AndroidLauncher : AndroidApplication() {
private var customSaveLocationHelper: CustomSaveLocationHelperAndroid? = null
private var game: UncivGame? = null
private var deepLinkedMultiplayerGame: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
customSaveLocationHelper = CustomSaveLocationHelperAndroid(this)
}
customSaveLocationHelper = CustomSaveLocationHelperAndroid(this)
MultiplayerTurnCheckWorker.createNotificationChannels(applicationContext)
// Only allow mods on KK+, to avoid READ_EXTERNAL_STORAGE permission earlier versions need
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
copyMods()
val externalfilesDir = getExternalFilesDir(null)
if (externalfilesDir != null) GameSaver.externalFilesDirForAndroid = externalfilesDir.path
}
copyMods()
val externalfilesDir = getExternalFilesDir(null)
if (externalfilesDir != null) GameSaver.externalFilesDirForAndroid = externalfilesDir.path
// Manage orientation lock
val limitOrientationsHelper = LimitOrientationsHelperAndroid(this)
@ -44,8 +41,18 @@ open class AndroidLauncher : AndroidApplication() {
customSaveLocationHelper = customSaveLocationHelper,
limitOrientationsHelper = limitOrientationsHelper
)
val game = UncivGame(androidParameters)
game = UncivGame(androidParameters)
initialize(game, config)
// This is also needed in onCreate to open links and notifications
// correctly even if the app was not running
if (intent.action == Intent.ACTION_VIEW) {
val uri: Uri? = intent.data
deepLinkedMultiplayerGame = uri?.getQueryParameter("id")
} else {
deepLinkedMultiplayerGame = null
}
}
/**
@ -84,15 +91,30 @@ open class AndroidLauncher : AndroidApplication() {
}
} catch (ex: Exception) {
}
if (deepLinkedMultiplayerGame != null) {
game?.deepLinkedMultiplayerGame = deepLinkedMultiplayerGame;
deepLinkedMultiplayerGame = null
}
super.onResume()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// This should only happen on API 19+ but it's wrapped in the if check to keep the
// compiler happy
customSaveLocationHelper?.handleIntentData(requestCode, data?.data)
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent == null)
return
if (intent.action == Intent.ACTION_VIEW) {
val uri: Uri? = intent.data
deepLinkedMultiplayerGame = uri?.getQueryParameter("id")
} else {
deepLinkedMultiplayerGame = null
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
customSaveLocationHelper?.handleIntentData(requestCode, data?.data)
super.onActivityResult(requestCode, resultCode, data)
}
}

View File

@ -6,6 +6,7 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationCompat.DEFAULT_VIBRATE
@ -138,17 +139,18 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
}
}
fun notifyUserAboutTurn(applicationContext: Context, gameName: String) {
val pendingIntent: PendingIntent =
Intent(applicationContext, AndroidLauncher::class.java).let { notificationIntent ->
PendingIntent.getActivity(applicationContext, 0, notificationIntent, 0)
}
fun notifyUserAboutTurn(applicationContext: Context, game: Pair<String, String>) {
val intent = Intent(applicationContext, AndroidLauncher::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse("https://unciv.app/multiplayer?id=${game.second}")
}
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, 0)
val contentTitle = applicationContext.resources.getString(R.string.Notify_YourTurn_Short)
val notification: NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL_ID_INFO)
.setPriority(NotificationManagerCompat.IMPORTANCE_HIGH) // people are waiting!
.setContentTitle(contentTitle)
.setContentText(applicationContext.resources.getString(R.string.Notify_YourTurn_Long).replace("[gameName]", gameName))
.setContentText(applicationContext.resources.getString(R.string.Notify_YourTurn_Long).replace("[gameName]", game.first))
.setTicker(contentTitle)
// without at least vibrate, some Android versions don't show a heads-up notification
.setDefaults(DEFAULT_VIBRATE)
@ -190,7 +192,7 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
// Of the turnNotification is OFF, this will be -1 since we never saved this game in the array
// Or possibly reading the preview file returned an exception
if (gameIndex!=-1)
notifyUserAboutTurn(applicationContext, gameNames[gameIndex])
notifyUserAboutTurn(applicationContext, Pair(gameNames[gameIndex], gameIds[gameIndex]))
} else {
val inputData = workDataOf(Pair(FAIL_COUNT, 0), Pair(GAME_ID, gameIds), Pair(GAME_NAME, gameNames),
Pair(USER_ID, settings.userId), Pair(CONFIGURED_DELAY, settings.multiplayerTurnCheckerDelayInMinutes),
@ -238,8 +240,8 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
val gameNames = inputData.getStringArray(GAME_NAME)!!
var arrayIndex = 0
// We only want to notify the user or update persisted notification once but still want
// to download all games to update the files hence this bool
var foundGame = ""
// to download all games to update the files so we save the first one we find
var foundGame: Pair<String, String>? = null
for (gameId in gameIds){
//gameId could be an empty string if startTurnChecker fails to load all files
@ -260,10 +262,8 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
*/
GameSaver.saveGame(gamePreview, gameNames[arrayIndex])
if (currentTurnPlayer.playerId == inputData.getString(USER_ID)!! && foundGame.isEmpty()) {
// We only save the first found game as the player will go into the
// multiplayer screen anyway to join the game and see the other ones
foundGame = gameNames[arrayIndex]
if (currentTurnPlayer.playerId == inputData.getString(USER_ID)!! && foundGame == null) {
foundGame = Pair(gameNames[arrayIndex], gameIds[arrayIndex])
}
arrayIndex++
} catch (ex: FileNotFoundException){
@ -276,7 +276,7 @@ class MultiplayerTurnCheckWorker(appContext: Context, workerParams: WorkerParame
}
}
if (foundGame.isNotEmpty()){
if (foundGame != null){
notifyUserAboutTurn(applicationContext, foundGame)
with(NotificationManagerCompat.from(applicationContext)) {
cancel(NOTIFICATION_ID_SERVICE)