Skip to content

Commit

Permalink
feat: initialize native request support on android
Browse files Browse the repository at this point in the history
  • Loading branch information
klxiaoniu committed Dec 27, 2024
1 parent 6ceea47 commit daef4dc
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 30 deletions.
12 changes: 11 additions & 1 deletion app/(tabs)/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ export default function HomePage() {
try {
const response = await post(url, headers, formData);
setDictionary(response);
Alert.alert('结果', JSON.stringify(response));
} catch (error) {
Alert.alert('错误', String(error));
}
};

const handlePressGet = async () => {
try {
const response = await get('https://jwch.fzu.edu.cn');
Alert.alert('结果', response);
} catch (error) {
Alert.alert('错误', String(error));
Expand All @@ -33,7 +42,8 @@ export default function HomePage() {
<>
<ThemedView>
<Text>User</Text>
<Button title="获取数据" onPress={handlePress} />
<Button title="获取数据POST" onPress={handlePress} />
<Button title="获取数据GET" onPress={handlePressGet} />
{Object.entries(dictionary).map(([key, value]) => (
<Text key={key}>
{key}: {value}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,135 @@ package com.west2online.nativerequest

import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.OutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import java.security.cert.X509Certificate
import javax.net.ssl.*

class NativeRequestModule : Module() {
// Each module class must implement the definition function. The definition consists of components
// that describes the module's functionality and behavior.
// See https://docs.expo.dev/modules/module-api for more details about available components.
override fun definition() = ModuleDefinition {
// Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
// The module will be accessible from `requireNativeModule('NativeRequest')` in JavaScript.
Name("NativeRequest")

// Sets constant properties on the module. Can take a dictionary or a closure that returns a dictionary.
Constants(
"PI" to Math.PI
)

// Defines event names that the module can send to JavaScript.
Events("onChange")

// Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
Function("hello") {
"Hello world! 👋"
}
// Each module class must implement the definition function. The definition consists of components
// that describes the module's functionality and behavior.
// See https://docs.expo.dev/modules/module-api for more details about available components.
override fun definition() = ModuleDefinition {
// Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
// The module will be accessible from `requireNativeModule('NativeRequest')` in JavaScript.
Name("NativeRequest")


fun createAllTrustingSSLContext(): SSLContext {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
override fun checkClientTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}

override fun checkServerTrusted(
chain: Array<out X509Certificate>?,
authType: String?
) {
}

override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
})

val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
return sslContext
}

AsyncFunction("get") { url: String ->
val urlConnection = URL(url).openConnection() as HttpURLConnection
urlConnection.requestMethod = "GET"

try {
val responseCode = urlConnection.responseCode
if (responseCode in 200..299) {
BufferedReader(
InputStreamReader(
urlConnection.inputStream,
StandardCharsets.UTF_8
)
).use { reader ->
val content = StringBuilder()
var line: String?
while (reader.readLine().also { line = it } != null) {
content.append(line)
}
return@AsyncFunction content.toString() + " Android"
}
} else {
return@AsyncFunction "请求失败,状态码: $responseCode"
}
} catch (e: Exception) {
return@AsyncFunction "请求失败: ${e.message}"
} finally {
urlConnection.disconnect()
}
}

// Defines a JavaScript function that always returns a Promise and whose native code
// is by default dispatched on the different thread than the JavaScript runtime runs on.
AsyncFunction("setValueAsync") { value: String ->
// Send an event to JavaScript.
sendEvent("onChange", mapOf(
"value" to value
))
AsyncFunction("post") { url: String, headers: Map<String, String>, formData: Map<String, String> ->
val sslContext = createAllTrustingSSLContext()
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory)
HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }

val urlObj = URL(url)
val urlConnection = urlObj.openConnection() as HttpURLConnection
urlConnection.requestMethod = "POST"

headers.forEach { (key, value) ->
urlConnection.setRequestProperty(key, value)
}

urlConnection.doOutput = true
urlConnection.doInput = true

val postData = formData.entries.joinToString("&") {
"${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}"
}.encodeToByteArray()

urlConnection.outputStream.use { outputStream ->
outputStream.write(postData)
outputStream.flush()
}

val responseCode = urlConnection.responseCode
val responseMessage = StringBuilder()
val result = mutableMapOf<String, Any>()
try {
result["status"] = responseCode
if (responseCode in 200..299) {
BufferedReader(
InputStreamReader(
urlConnection.inputStream,
StandardCharsets.UTF_8
)
).use { reader ->
var line: String?
while (reader.readLine().also { line = it } != null) {
responseMessage.append(line)
}
}
result["data"] = responseMessage.toString()
} else {
result["data"] = ""
}
result["set-cookies"] =
urlConnection.headerFields["Set-Cookie"]?.joinToString("; ") ?: ""
} catch (e: Exception) {
result["error"] = "请求失败: ${e.message}"
} finally {
urlConnection.disconnect()
}

return@AsyncFunction result
}
}
}

}

0 comments on commit daef4dc

Please sign in to comment.