Sfoglia il codice sorgente

Added Android Support (#3744)

### Goals :soccer:
<!-- List the high-level objectives of this pull request. -->
The goal of this pull request is to add Android support to Alamofire.
<!-- Include any relevant context. -->
The following changes were verified on the swift-5.8 toolchain built for
Android.

### Implementation Details :construction:
<!-- Explain the reasoning behind any architectural changes. -->
<!-- Highlight any new functionality. -->
Alamofire should work flawlessly against an android swift toolchain
(tested with version 5.8) with the same limitations and context as the
current support on Linux + Windows.


### Testing Details :mag:
<!-- Describe what tests you've added for your changes. -->
No new unit tests were added.

The following context + assumptions are in place for ensuring this works
as expected:

- built as a swift package manager dependency on a swift 5.8 or above
toolchain
- swift binary artifact is linked dynamically against an NDK (tested on
r25c) android (api level 30) application
- the following gnu c libs must also be dynamically linked and loaded at
runtime in your MainActivity
  - libcrypto
  - libssl
  - libz
 (feel free to grab these from the termux repo dev snapshots)

Tested on android api level 30, architectures: x86_64, arm64

---------

Co-authored-by: Jon Shier <jon@jonshier.com>
Hugo Gonzalez 2 anni fa
parent
commit
bf689d61ba

+ 8 - 0
.github/workflows/ci.yml

@@ -272,6 +272,14 @@ jobs:
       - uses: actions/checkout@v3
       - name: ${{ matrix.image }}
         run: swift build --build-tests -c debug
+  Android:
+    name: Android
+    uses: hggz/swift-android-sdk/.github/workflows/sdks.yml@ci
+    strategy:
+      fail-fast: false
+    with:
+      target-repo: ${{ github.repository }}
+      checkout-hash: ${{ github.sha }}
   Windows:
     name: Windows
     runs-on: windows-latest

+ 1 - 1
Source/Combine.swift

@@ -22,7 +22,7 @@
 //  THE SOFTWARE.
 //
 
-#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux))
+#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux) || os(Android))
 
 import Combine
 import Dispatch

+ 2 - 0
Source/HTTPHeaders.swift

@@ -399,6 +399,8 @@ extension HTTPHeader {
                 return "Linux"
                 #elseif os(Windows)
                 return "Windows"
+                #elseif os(Android)
+                return "Android"
                 #else
                 return "Unknown"
                 #endif

+ 1 - 1
Source/MultipartFormData.swift

@@ -213,7 +213,7 @@ open class MultipartFormData {
         //              Check 2 - is file URL reachable?
         //============================================================
 
-        #if !(os(Linux) || os(Windows))
+        #if !(os(Linux) || os(Windows) || os(Android))
         do {
             let isReachable = try fileURL.checkPromisedItemIsReachable()
             guard isReachable else {

+ 2 - 2
Source/Protected.swift

@@ -49,7 +49,7 @@ extension Lock {
     }
 }
 
-#if os(Linux) || os(Windows)
+#if os(Linux) || os(Windows) || os(Android)
 
 extension NSLock: Lock {}
 
@@ -86,7 +86,7 @@ final class UnfairLock: Lock {
 final class Protected<T> {
     #if canImport(Darwin)
     private let lock = UnfairLock()
-    #elseif os(Linux) || os(Windows)
+    #elseif os(Linux) || os(Windows) || os(Android)
     private let lock = NSLock()
     #endif
     private var value: T

+ 1 - 1
Source/RequestTaskMap.swift

@@ -131,7 +131,7 @@ struct RequestTaskMap {
 
         switch (events.completed, events.metricsGathered) {
         case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
-        #if os(Linux) // Linux doesn't gather metrics, so unconditionally remove the reference and return true.
+        #if os(Linux) || os(Android) // Linux doesn't gather metrics, so unconditionally remove the reference and return true.
         default: self[task] = nil; return true
         #else
         case (false, false):

+ 3 - 3
Source/ServerTrustEvaluation.swift

@@ -75,8 +75,8 @@ open class ServerTrustManager {
 
 /// A protocol describing the API used to evaluate server trusts.
 public protocol ServerTrustEvaluating {
-    #if os(Linux) || os(Windows)
-    // Implement this once Linux/Windows has API for evaluating server trusts.
+    #if !canImport(Security)
+    // Implement this once other platforms have API for evaluating server trusts.
     #else
     /// Evaluates the given `SecTrust` value for the given `host`.
     ///
@@ -457,7 +457,7 @@ public final class DisabledTrustEvaluator: ServerTrustEvaluating {
 // MARK: - Extensions
 
 extension Array where Element == ServerTrustEvaluating {
-    #if os(Linux) || os(Windows)
+    #if os(Linux) || os(Windows) || os(Android)
     // Add this same convenience method for Linux/Windows.
     #else
     /// Evaluates the given `SecTrust` value for the given `host`.

+ 1 - 1
Tests/AuthenticationInterceptorTests.swift

@@ -288,7 +288,7 @@ final class AuthenticationInterceptorTestCase: BaseTestCase {
     }
 
     // MARK: - Tests - Retry
-
+  
     // If we not using swift-corelibs-foundation where URLRequest to /invalid/path is a fatal error.
     #if !canImport(FoundationNetworking)
     func testThatInterceptorDoesNotRetryWithoutResponse() {

+ 1 - 1
Tests/CombineTests.swift

@@ -22,7 +22,7 @@
 //  THE SOFTWARE.
 //
 
-#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux))
+#if !((os(iOS) && (arch(i386) || arch(arm))) || os(Windows) || os(Linux) || os(Android))
 
 import Alamofire
 import Combine

+ 1 - 1
Tests/ResponseSerializationTests.swift

@@ -1400,7 +1400,7 @@ final class StaticDataPreprocessorTests: BaseTestCase {
 extension HTTPURLResponse {
     convenience init(statusCode: Int, headers: HTTPHeaders? = nil) {
         let url = Endpoint().url
-        #if os(watchOS) || os(Linux) || os(Windows)
+        #if os(watchOS) || os(Linux) || os(Windows) || os(Android)
         let httpVersion = "HTTP/1.1"
         #else
         let httpVersion = String(kCFHTTPVersion1_1)

+ 2 - 0
Tests/SessionTests.swift

@@ -313,6 +313,8 @@ final class SessionTestCase: BaseTestCase {
                 return "macOS"
                 #elseif os(Linux)
                 return "Linux"
+                #elseif os(Android)
+                return "Android"
                 #else
                 return "Unknown"
                 #endif