반응형
https://github.com/ahmedmolawale/AndroidNanoHttpd
오늘은 번외 편으로 안드로이드를 이용한 웹서버 간략 구현에 대해서 알아볼까 합니다. 이 포스팅은 위 링크의 글을 참조하였음을 밝혀 둡니다.
Gradle 추가
// nano HTTP 구현
implementation 'com.nanohttpd:nanohttpd:2.2.0'
이거 하나 추가 하면 끝입니다. 다음은 Local에서 WebServer로 사용할 코드를 구현해 보겠습니다.
import android.content.Context
import android.os.StatFs
import android.util.Log
import androidx.core.content.ContextCompat
import fi.iki.elonen.NanoHTTPD
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.net.Inet4Address
import java.net.NetworkInterface
import java.net.SocketException
class LocalWebserver(context: Context, port: Int) : NanoHTTPD(port) {
var context: Context? = context
val MIME_JAVASCRIPT = "text/javascript"
val MIME_CSS = "text/css"
val MIME_JPEG = "image/jpeg"
val MIME_PNG = "image/png"
val MIME_SVG = "image/svg+xml"
val MIME_JSON = "application/json"
val MIME_GIF = "image/gif"
val MIME_BMP = "image/bmp"
var mimeType = MIME_HTML
val folderName = "portfolio" //name of the folder holding the asset of the page you wanna load
val TAG = "LocalWebserver"
override fun serve(session: IHTTPSession?): Response? {
val uri = session?.uri
try {
when {
uri!!.endsWith(".js") -> {
mimeType = MIME_JAVASCRIPT
}
uri.endsWith(".css") -> {
mimeType = MIME_CSS
}
uri.endsWith(".html") -> {
mimeType = MIME_HTML
}
uri.endsWith(".jpeg") -> {
mimeType = MIME_JPEG
}
uri.endsWith(".png") -> {
mimeType = MIME_PNG
}
uri.endsWith(".jpg") -> {
mimeType = MIME_JPEG
}
uri.endsWith(".svg") -> {
mimeType = MIME_SVG
}
uri.endsWith(".bmp") -> {
mimeType = MIME_BMP
}
uri.endsWith(".gif") -> {
mimeType = MIME_GIF
}
uri.endsWith(".json") -> {
mimeType = MIME_JSON
}
}
} catch (e: Exception) {
Log.e(TAG, "MINE ERROR ... ${e.message}")
}
Log.e(TAG, "${getLocalIpAddress()} ${getStoragePath()}")
val root = "${getStoragePath()}${File.separator}"
var fis: FileInputStream? = null
val file = File(
root +
"${folderName}/${uri}"
)
try {
if (file.exists()) {
fis = FileInputStream(file);
}
} catch (ioe: IOException) {
Log.e("Httpd %s", ioe.toString())
}
return newFixedLengthResponse(
Response.Status.OK,
mimeType,
fis,
file.length()
)
}
private fun getStoragePath(): String? {
var path: String? = null
var space: Long = 0
val files: Array<File> = ContextCompat.getExternalFilesDirs(context!!, null)
// go through the options to choose one with more available storage capacity
for (f in files) {
val stat = StatFs(f.path)
val blockSize = stat.blockSizeLong
val totalBlocks = stat.blockCountLong
// check if storage capacity is more than the previous one
if (totalBlocks * blockSize > space) {
space = totalBlocks * blockSize
path = f.path
}
}
return path
}
private fun getLocalIpAddress(): String {
try {
val en = NetworkInterface.getNetworkInterfaces()
while (en.hasMoreElements()) {
val intf = en.nextElement()
val enumIpAddr = intf.inetAddresses
while (enumIpAddr.hasMoreElements()) {
val inetAddress = enumIpAddr.nextElement()
if (!inetAddress.isLoopbackAddress && inetAddress is Inet4Address) {
return inetAddress.getHostAddress().toString()
}
}
}
} catch (ex: SocketException) {
ex.printStackTrace()
}
return ""
}
}
코드는 참조한 링크의 내용을 그대로 구현 했습니다. 잘 모르는 부분도 있고 해서요. 코드를 보면 local IP을 확인하고, 해당 아이피를 기준으로 웹서버를 구동하는 그런 정도입니다. 추가적으로 해야 할 부분은 이제 화면에서 보여줄 html 코드를 구현해 보는 것인데,
아직은 그럴 생각이 없기 때문에 그냥 이렇게 구현 하는 정도까지만 포스팅을 해 두겠습니다. 이제 실행을 해 볼까요?
웹서버 구동
var localWebserver = LocalWebserver(this@MainActivity, 8035)
localWebserver.start()
이런 정도의 코드 구현으로 구현이 됩니다. 그러면 위 구현된 코드에서 getStoreagePath()에서 구해온 경로에 index.html을 등을 넣어 주면 호출이 되는 것을 알 수 있었습니다.
크롬 등으로 현재 테스트 중인 앱의 서버에 접속을 해 보고 그 실행 로그가 출력되는 것을 확인하였습니다. 지금은 내가 사용하는 스마트폰에 wifi debugging을 실행하고 앱을 빌드해서 실행해 본 것입니다.
이것으로 로컬 웹서버가 필요한 경우 구현해 볼 수 있을 것 같습니다.
반응형
'모바일 앱(안드로이드)' 카테고리의 다른 글
개발일기 # 번외편3 : 앱의 디자인에 대한 평가 받아 보기 (0) | 2022.11.16 |
---|---|
개발일기 # 번외편2 : 난 서버가 없는데(Serverless) cloud function 사용해 보기 (0) | 2022.11.12 |
안드로이드 앱 만들기 : Admob 버전 별 구글 광고 중단 일정. (0) | 2022.11.05 |
개발일기 #10 진행율 표시는 어떻게 progressbar 만들기 (2) | 2022.11.03 |
개발일기 #9 : 실시간 카메라 권한 획득 방법 Jetpack Compose (0) | 2022.11.02 |