最近接到一个需求,由后台主动给APP发送消息,且对实时性的要求较高。
经过探索评估,发现NanoHTTPD很适合,非常轻便。
本文主要内容如下:
1、依赖导入;
2、设置IP和端口;
3、启动服务和后台运行优化;
4、Demo的Github地址;
5、并发请求问题。
1、依赖导入
implementation 'org.nanohttpd:nanohttpd:2.3.1'
2、设置IP和端口
创建 HttpServer 继承抽象类 NanoHTTPD,可按需创建一个或两个构造函数,设置IP和端口号。
【重点】其中IP地址为当前手机网络的IP地址,否则开启该服务时会报错。
// IP 和 POST
const val HTTP_IP = "192.168.51.101"
const val HTTP_PORT = 8080
服务器实现:
import fi.iki.elonen.NanoHTTPD
class HttpServer(hostname: String?, port: Int) : NanoHTTPD(hostname, port) {
// 服务的核心方法,在这里处理请求和数据返回,现直接返回字符串Request success!
override fun serve(session: IHTTPSession?): Response {
return newFixedLengthResponse("Request success!");
}
}
在APP首页中开启服务:
class MainActivity : AppCompatActivity() {
private lateinit var mHttpServer: HttpServer
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mHttpServer = HttpServer(HTTP_IP, HTTP_PORT)
try {
mHttpServer.start()
}catch (e: Exception){
e.printStackTrace()
}
}
override fun onDestroy() {
mHttpServer.stop()
super.onDestroy()
}
}
当然别忘了在清单文件中添加网络请求权限
<uses-permission android:name="android.permission.INTERNET" />
至此,你就可以在浏览器上输入地址,http://192.168.51.101:8080/
3、启动服务和后台运行优化
使用上面的方式,当MainActivity 页面被销毁后,服务将连接不上;所以改进一下,创建一个MainService来开启和关闭该服务
import android.app.Service
import android.content.Intent
import android.os.IBinder
class MainService : Service() {
private var mHttpServer: HttpServer? = null
override fun onCreate() {
super.onCreate()
mHttpServer = HttpServer(HTTP_IP, HTTP_PORT)
try {
mHttpServer?.start()
}catch (e: Exception){
e.printStackTrace()
val service = Intent(this, MainService::class.java)
startService(service)
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onDestroy() {
mHttpServer?.stop()
super.onDestroy()
}
}
清单文件中注册:
<service android:name="com.ljt.katp.server.MainService" />
并将MainActivity修改为:
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.ljt.katp.server.MainService
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val service = Intent(this, MainService::class.java)
startService(service)
}
override fun onDestroy() {
super.onDestroy()
}
}
如果想要APP保持服务持久可用,又不被系统限制网络,,可以进入系统设置中设置“电池不优化”。一加5手机设置如下:
4、Demo的git地址
https://github.com/SmarterBoy/katp
Demo中提供一些简单的(POST、GET)接口定义,请求头、参数获取,以及Json数据返回。
5、并发请求问题?
根据之前的并发请求测试发现,只会返回同一条数据,而不是分别响应每一个接口请求。
目前尚未找到适合的处理方式,暂且只能控制请求端的请求频次。