Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on: [pull_request]

env:
BUNDLE_PATH: vendor/bundle
DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_26.1.app/Contents/Developer

concurrency:
group: ${{ github.ref }}
Expand Down Expand Up @@ -56,7 +56,7 @@ jobs:
xcodebuild \
-project AirshipFrameworkProxy.xcodeproj \
-scheme AirshipFrameworkProxy \
-destination 'platform=iOS Simulator,OS=18.4,name=iPhone 16 Pro Max' \
-destination 'platform=iOS Simulator,OS=26.1,name=iPhone 17 Pro Max' \
clean test | xcbeautify --renderer github-actions

- name: Pod lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

env:
BUNDLE_PATH: vendor/bundle
DEVELOPER_DIR: /Applications/Xcode_16.4.app/Contents/Developer
DEVELOPER_DIR: /Applications/Xcode_26.1.app/Contents/Developer

jobs:
android:
Expand Down
6 changes: 3 additions & 3 deletions AirshipFrameworkProxy.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

Pod::Spec.new do |s|
s.version = "14.10.1"
s.version = "15.0.0"
s.name = "AirshipFrameworkProxy"
s.summary = "Airship iOS mobile framework proxy"
s.documentation_url = "https://docs.airship.com/platform/mobile"
Expand All @@ -11,11 +11,11 @@ Pod::Spec.new do |s|
s.source = { :git => "https://github.com/urbanairship/airship-mobile-framework-proxy.git", :tag => s.version.to_s }

s.module_name = "AirshipFrameworkProxy"
s.ios.deployment_target = "15.0"
s.ios.deployment_target = "16.0"
s.requires_arc = true
s.swift_version = "6.0"
s.source_files = "ios/AirshipFrameworkProxy/**/*.{h,m,swift}"
s.dependency 'Airship', "19.11.2"
s.dependency 'Airship', "20.0.2"
s.source_files = 'ios/AirshipFrameworkProxyLoader/**/*.{swift,h,m,c,cc,mm,cpp}', 'ios/AirshipFrameworkProxy/**/*.{swift,h,m,c,cc,mm,cpp}'
end

Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import PackageDescription
let package = Package(
name: "AirshipFrameworkProxy",
defaultLocalization: "en",
platforms: [.macOS(.v10_15), .iOS(.v15), .tvOS(.v18), .visionOS(.v1)],
platforms: [.iOS(.v16), .tvOS(.v18), .visionOS(.v1)],
products: [
.library(
name: "AirshipFrameworkProxy",
targets: ["AirshipFrameworkProxy", "AirshipFrameworkProxyLoader"]
)
],
dependencies: [
.package(url: "https://github.com/urbanairship/ios-library.git", from: "19.11.2")
.package(url: "https://github.com/urbanairship/ios-library.git", from: "20.0.2")
],
targets: [
.target(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.urbanairship.android.framework.proxy

import com.urbanairship.UAirship
import com.urbanairship.Airship
import com.urbanairship.actions.DeepLinkListener
import com.urbanairship.android.framework.proxy.events.ChannelCreatedEvent
import com.urbanairship.android.framework.proxy.events.DeepLinkEvent
Expand Down Expand Up @@ -43,13 +43,12 @@ internal class AirshipListener(
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
private val isAppForegrounded: Boolean
get() {
return GlobalActivityMonitor.shared(UAirship.getApplicationContext()).isAppForegrounded
return GlobalActivityMonitor.shared(Airship.application).isAppForegrounded
}

@Suppress("deprecation")
private val forwardNotificationListener: NotificationListener?
get() {
return AirshipPluginExtensions.forwardNotificationListener ?: AirshipPluginForwardListeners.notificationListener
return AirshipPluginExtensions.forwardNotificationListener
}

override fun onShowMessageCenter(messageId: String?): Boolean {
Expand Down Expand Up @@ -95,38 +94,30 @@ internal class AirshipListener(

override fun onNotificationForegroundAction(
notificationInfo: NotificationInfo,
notificationActionButtonInfo: NotificationActionButtonInfo
actionButtonInfo: NotificationActionButtonInfo
): Boolean {
eventEmitter.addEvent(
NotificationResponseEvent(notificationInfo, notificationActionButtonInfo)
NotificationResponseEvent(notificationInfo, actionButtonInfo)
)
return forwardNotificationListener?.onNotificationForegroundAction(notificationInfo, notificationActionButtonInfo) ?: false
return forwardNotificationListener?.onNotificationForegroundAction(notificationInfo, actionButtonInfo) ?: false
}

override fun onNotificationBackgroundAction(
notificationInfo: NotificationInfo,
notificationActionButtonInfo: NotificationActionButtonInfo
actionButtonInfo: NotificationActionButtonInfo
) {
eventEmitter.addEvent(
NotificationResponseEvent(notificationInfo, notificationActionButtonInfo)
NotificationResponseEvent(notificationInfo, actionButtonInfo)
)
forwardNotificationListener?.onNotificationBackgroundAction(notificationInfo, notificationActionButtonInfo)
forwardNotificationListener?.onNotificationBackgroundAction(notificationInfo, actionButtonInfo)
}

override fun onNotificationDismissed(notificationInfo: NotificationInfo) {
forwardNotificationListener?.onNotificationDismissed(notificationInfo)
}

@Suppress("deprecation")
override fun onDeepLink(deepLink: String): Boolean {
val override = AirshipPluginExtensions.onDeepLink?.invoke(deepLink)
if (override == null) {
if (AirshipPluginForwardListeners.deepLinkListener?.onDeepLink(deepLink) == true) {
ProxyLogger.debug("Deeplink handling for $deepLink overridden by deprecated forward delegate")
return true
}
}

when(override) {
is AirshipPluginOverride.Override -> {
ProxyLogger.debug("Deeplink handling for $deepLink overridden by plugin extension")
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package com.urbanairship.android.framework.proxy

import android.content.Context
import com.urbanairship.AirshipConfigOptions
import com.urbanairship.UAirship

/**
* Extender that will be called during `takeOff` to customize the Airship instance.
Expand Down Expand Up @@ -43,9 +42,8 @@ public interface AirshipPluginExtender {
* to process notifications.
*
* @param context The application context.
* @param airship The airship instance.
*/
public fun onAirshipReady(context: Context, airship: UAirship)
public fun onAirshipReady(context: Context)

/**
* Used to extend the AirshipConfig. The configBuilder will have the default config applied from the properties file if available,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@

package com.urbanairship.android.framework.proxy

import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.net.Uri
import android.util.Log
import androidx.annotation.XmlRes
import com.urbanairship.Airship
import com.urbanairship.AirshipConfigOptions
import com.urbanairship.Autopilot
import com.urbanairship.Predicate
import com.urbanairship.UAirship
import com.urbanairship.android.framework.proxy.Utils.getHexColor
import com.urbanairship.android.framework.proxy.Utils.getNamedResource
import com.urbanairship.android.framework.proxy.events.EventEmitter
import com.urbanairship.android.framework.proxy.events.NotificationStatusEvent
Expand All @@ -29,6 +27,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import androidx.core.net.toUri

/**
* Module's autopilot to customize Urban Airship.
Expand All @@ -41,11 +40,9 @@ public abstract class BaseAutopilot : Autopilot() {

private val dispatcher = CoroutineScope(Dispatchers.Main + SupervisorJob())

final override fun onAirshipReady(airship: UAirship) {
super.onAirshipReady(airship)
final override fun onAirshipReady(context: Context) {

ProxyLogger.setLogLevel(airship.airshipConfigOptions.logLevel)
val context = UAirship.getApplicationContext()
ProxyLogger.setLogLevel(Airship.airshipConfigOptions.logLevel.level)

val proxyStore = AirshipProxy.shared(context).proxyStore
val airshipListener = AirshipListener(
Expand All @@ -57,11 +54,11 @@ public abstract class BaseAutopilot : Autopilot() {
MessageCenter.shared().setOnShowMessageCenterListener(airshipListener)
MessageCenter.shared().inbox.addListener(airshipListener)

airship.channel.addChannelListener(airshipListener)
airship.pushManager.addPushListener(airshipListener)
airship.pushManager.addPushTokenListener(airshipListener)
airship.pushManager.notificationListener = airshipListener
airship.deepLinkListener = airshipListener
Airship.channel.addChannelListener(airshipListener)
Airship.push.addPushListener(airshipListener)
Airship.push.addPushTokenListener(airshipListener)
Airship.push.notificationListener = airshipListener
Airship.deepLinkListener = airshipListener

dispatcher.launch {
PendingEmbedded.pending.collect {
Expand All @@ -74,8 +71,8 @@ public abstract class BaseAutopilot : Autopilot() {

dispatcher.launch {
combine(
airship.pushManager.pushNotificationStatusFlow,
airship.permissionsManager.permissionsUpdate(Permission.DISPLAY_NOTIFICATIONS)
Airship.push.pushNotificationStatusFlow,
Airship.permissionsManager.permissionsUpdate(Permission.DISPLAY_NOTIFICATIONS)
) { status, permissionStatus ->
NotificationStatus(status, permissionStatus.value)
}.filter {
Expand All @@ -90,9 +87,10 @@ public abstract class BaseAutopilot : Autopilot() {
}

// Set our custom notification provider
val notificationProvider = BaseNotificationProvider(context, airship.airshipConfigOptions)
airship.pushManager.notificationProvider = notificationProvider
airship.pushManager.foregroundNotificationDisplayPredicate = Predicate { message ->
val notificationProvider = BaseNotificationProvider(context, Airship.airshipConfigOptions)
notificationProvider.applyNotificationConfig(proxyStore.notificationConfig)
Airship.push.notificationProvider = notificationProvider
Airship.push.foregroundNotificationDisplayPredicate = Predicate { message ->
return@Predicate runBlocking {
val override = AirshipPluginExtensions.onShouldDisplayForegroundNotification?.invoke(message) ?: AirshipPluginOverride.UseDefault
return@runBlocking when(override) {
Expand All @@ -110,34 +108,36 @@ public abstract class BaseAutopilot : Autopilot() {
}
}

loadCustomNotificationChannels(context, airship)
loadCustomNotificationButtonGroups(context, airship)
loadCustomNotificationChannels(context)
loadCustomNotificationButtonGroups(context)

onReady(context, airship)
onReady(context)

extenderProvider.get(context)?.onAirshipReady(context, airship)
extenderProvider.get(context)?.onAirshipReady(context)
extenderProvider.reset()
}

protected abstract fun onReady(context: Context, airship: UAirship)
protected abstract fun onReady(context: Context)

private fun loadCustomNotificationChannels(context: Context, airship: UAirship) {
val packageName = UAirship.getPackageName()
@SuppressLint("DiscouragedApi")
private fun loadCustomNotificationChannels(context: Context) {
val packageName = context.packageName
@XmlRes val resId = context.resources.getIdentifier("ua_custom_notification_channels", "xml", packageName)

if (resId != 0) {
ProxyLogger.debug("Loading custom notification channels")
airship.pushManager.notificationChannelRegistry.createNotificationChannels(resId)
Airship.push.notificationChannelRegistry.createNotificationChannels(resId)
}
}

private fun loadCustomNotificationButtonGroups(context: Context, airship: UAirship) {
val packageName = UAirship.getPackageName()
@SuppressLint("DiscouragedApi")
private fun loadCustomNotificationButtonGroups(context: Context) {
val packageName = context.packageName
@XmlRes val resId = context.resources.getIdentifier("ua_custom_notification_buttons", "xml", packageName)

if (resId != 0) {
ProxyLogger.debug("Loading custom notification button groups")
airship.pushManager.addNotificationActionButtonGroups(context, resId)
Airship.push.addNotificationActionButtonGroups(context, resId)
}
}

Expand All @@ -160,7 +160,7 @@ public abstract class BaseAutopilot : Autopilot() {
configOptions.validate()
this.configOptions = configOptions
true
} catch (e: Exception) {
} catch (_: Exception) {
false
}
}
Expand Down Expand Up @@ -189,7 +189,7 @@ public fun AirshipConfigOptions.Builder.applyProxyConfig(context: Context, proxy
proxyConfig.developmentEnvironment?.let {
this.setDevelopmentAppKey(it.appKey)
.setDevelopmentAppSecret(it.appSecret)
.setDevelopmentLogLevel(it.logLevel ?: Log.DEBUG)
.setDevelopmentLogLevel(it.logLevel ?: AirshipConfigOptions.LogLevel.DEBUG)

proxyConfig.androidConfig?.logPrivacyLevel?.let { privacyLevel ->
this.setDevelopmentLogPrivacyLevel(privacyLevel)
Expand All @@ -199,7 +199,7 @@ public fun AirshipConfigOptions.Builder.applyProxyConfig(context: Context, proxy
proxyConfig.productionEnvironment?.let {
this.setProductionAppKey(it.appKey)
.setProductionAppSecret(it.appSecret)
.setProductionLogLevel(it.logLevel ?: Log.DEBUG)
.setProductionLogLevel(it.logLevel ?: AirshipConfigOptions.LogLevel.ERROR)

proxyConfig.androidConfig?.logPrivacyLevel?.let { privacyLevel ->
this.setProductionLogPrivacyLevel(privacyLevel)
Expand All @@ -209,7 +209,7 @@ public fun AirshipConfigOptions.Builder.applyProxyConfig(context: Context, proxy
proxyConfig.defaultEnvironment?.let {
this.setAppKey(it.appKey)
.setAppSecret(it.appSecret)
.setLogLevel(it.logLevel ?: Log.ERROR)
.setLogLevel(it.logLevel ?: AirshipConfigOptions.LogLevel.ERROR)
}

proxyConfig.site?.let { this.setSite(it) }
Expand All @@ -220,7 +220,7 @@ public fun AirshipConfigOptions.Builder.applyProxyConfig(context: Context, proxy
proxyConfig.urlAllowList?.let { this.setUrlAllowList(it.toTypedArray()) }
proxyConfig.urlAllowListScopeJavaScriptInterface?.let { this.setUrlAllowListScopeJavaScriptInterface(it.toTypedArray()) }
proxyConfig.urlAllowListScopeOpenUrl?.let { this.setUrlAllowListScopeOpenUrl(it.toTypedArray()) }
proxyConfig.androidConfig?.appStoreUri?.let { this.setAppStoreUri(Uri.parse(it)) }
proxyConfig.androidConfig?.appStoreUri?.let { this.setAppStoreUri(it.toUri()) }
proxyConfig.androidConfig?.fcmFirebaseAppName?.let { this.setFcmFirebaseAppName(it) }
proxyConfig.enabledFeatures?.let { this.setEnabledFeatures(it) }
proxyConfig.autoPauseInAppAutomationOnLaunch?.let { this.setAutoPauseInAppAutomationOnLaunch(it) }
Expand All @@ -237,7 +237,7 @@ public fun AirshipConfigOptions.Builder.applyProxyConfig(context: Context, proxy
}

notificationConfig.defaultChannelId?.let { this.setNotificationChannel(it) }
notificationConfig.accentColor?.let { this.setNotificationAccentColor(getHexColor(it, 0)) }
notificationConfig.accentColor?.let { this.setNotificationAccentColor(Utils.getHexColor(it, 0)) }
}
}

Expand Down Expand Up @@ -265,7 +265,7 @@ private class ExtenderProvider {
if (ai.metaData == null) {
return null
}
} catch (e: PackageManager.NameNotFoundException) {
} catch (_: PackageManager.NameNotFoundException) {
return null
}

Expand Down
Loading
Loading