您好,登錄后才能下訂單哦!
一般而言,Android 應用在請求數據時都是以 Get 或 Post 等方式向遠程服務器發起請求,那你有沒有想過其實我們也可以在 Android 設備上搭建一個小型 Web 服務器,并且實現常規的下載圖片、下載文件、提交表單等功能呢?
下面要介紹的就是如何在 Android 設備上搭建一個 Web 服務器,這個 Web 服務器的功能有如下幾點:
這需要依賴一個開源庫來實現:AndServer
AndServer 類似于 Apache 和 Tomcat,支持在同個局域網下的設備能夠以常規的網絡請求方式來向 Web 服務器請求數據,只要指明 Web 服務器的 IP 地址和端口號即可
那么,這個 Web 服務器的用途有哪些呢?
說下我現在遇到的一個需求吧!需要實現兩臺設備(Android 或 ios 設備)在無網絡情況下進行數據交流。本來是打算讓設備之間的交流通道以 Wifi 來鏈接,即某一臺設備連上另一臺設備的 Wiif 熱點,這樣兩者之間就建立起了一條“通道”,之后通過建立 Socket 連接來獲取輸入輸出流,通過輸入輸出流來交換數據。可是這樣就需要處理好在高并發情況下的數據同步和解析問題,比較麻煩,而通過 AndServer 就可以直接套用項目已有的網絡請求框架,直接以網絡請求的方式來交流數據,而服務端也較好的處理了并發問題
Gradle 遠程依賴
implementation 'com.yanzhenjie:andserver:1.1.3'
搭建服務器
搭建服務器的方式很簡單,支持鏈式調用。指明服務器在本機的 IP 地址上監聽,并指定端口號為 1995 ,并開放了三個接口分別用于:下載文件、下載圖片、Post表單
AndServer server = AndServer.serverBuilder() .inetAddress(NetUtils.getLocalIPAddress()) //服務器要監聽的網絡地址 .port(Constants.PORT_SERVER) //服務器要監聽的端口 .timeout(10, TimeUnit.SECONDS) //Socket超時時間 .registerHandler(Constants.GET_FILE, new DownloadFileHandler()) //注冊一個文件下載接口 .registerHandler(Constants.GET_IMAGE, new DownloadImageHandler()) //注冊一個圖片下載接口 .registerHandler(Constants.POST_JSON, new JsonHandler()) //注冊一個Post Json接口 .filter(new HttpCacheFilter()) //開啟緩存支持 .listener(new Server.ServerListener() { //服務器監聽接口 @Override public void onStarted() { String hostAddress = server.getInetAddress().getHostAddress(); Log.e(TAG, "onStarted : " + hostAddress); ServerPresenter.onServerStarted(ServerService.this, hostAddress); } @Override public void onStopped() { Log.e(TAG, "onStopped"); ServerPresenter.onServerStopped(ServerService.this); } @Override public void onError(Exception e) { Log.e(TAG, "onError : " + e.getMessage()); ServerPresenter.onServerError(ServerService.this, e.getMessage()); } }) .build();
開啟服務器
server.startup();
停止服務器
server.shutdown();
接口處理器
在注冊接口時,除了指明開放出來的 Url 地址外,還需要指明相應的處理器,專門用于處理該接口的請求操作
開放出來的三個接口分別對應于三個地址
public class Constants { //服務端接口的端口號 public static final int PORT_SERVER = 1995; public static final String GET_FILE = "/file"; public static final String GET_IMAGE = "/image"; public static final String POST_JSON = "/json"; }
··· .registerHandler(Constants.GET_FILE, new DownloadFileHandler()) //注冊一個文件下載接口 .registerHandler(Constants.GET_IMAGE, new DownloadImageHandler()) //注冊一個圖片下載接口 .registerHandler(Constants.POST_JSON, new JsonHandler()) //注冊一個Post Json接口 ···
例如,假設設備的 IP 地址是:192.168.0.101 ,那么在訪問 http://192.168.0.101:1995/file 接口時,請求操作就會由 DownloadFileHandler 來處理
下載文件
DownloadFileHandler 實現了 RequestHandler 接口,在 handle 方法中可以獲取到請求頭,表單數據這些信息,,通過注解聲明支持 Get 方式調用,在此直接返回一個文本文件用于下載
/** * 作者:leavesC * 時間:2018/4/5 16:30 * 描述:https://github.com/leavesC/AndroidServer */ public class DownloadFileHandler implements RequestHandler { @RequestMapping(method = {RequestMethod.GET}) @Override public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException { File file = createFile(); HttpEntity httpEntity = new FileEntity(file, ContentType.create(getMimeType(file.getAbsolutePath()), Charset.defaultCharset())); httpResponse.setHeader("Content-Disposition", "attachment;filename=File.txt"); httpResponse.setStatusCode(200); httpResponse.setEntity(httpEntity); } private File createFile() { File file = null; OutputStream outputStream = null; try { file = File.createTempFile("File", ".txt", MainApplication.get().getCacheDir()); outputStream = new FileOutputStream(file); outputStream.write("leavesC,這是一段測試文本".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.flush(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return file; } }
這里直接在瀏覽器中訪問接口(要和 Android Web服務器運行在同個局域網下),可以直接下載到文件
下載圖片
類似的,下載圖片的接口處理器 DownloadImageHandler 可以如下設計,在 handle 方法中返回應用的圖標
/** * 作者:leavesC * 時間:2018/4/5 16:30 * 描述:https://github.com/leavesC/AndroidServer */ public class DownloadImageHandler extends SimpleRequestHandler { private File file = new File(Environment.getExternalStorageDirectory(), "leavesC.jpg"); @RequestMapping(method = {RequestMethod.GET}) @Override protected View handle(HttpRequest request) throws HttpException, IOException { writeToSdCard(); HttpEntity httpEntity = new FileEntity(file, ContentType.create(getMimeType(file.getAbsolutePath()), Charset.defaultCharset())); return new View(200, httpEntity); } private void writeToSdCard() throws IOException { if (!file.exists()) { synchronized (DownloadImageHandler.class) { if (!file.exists()) { boolean b = file.createNewFile(); if (!b) { throw new IOException("What broken cell phone."); } Bitmap bitmap = BitmapFactory.decodeResource(MainApplication.get().getResources(), R.mipmap.ic_launcher_round); OutputStream outputStream = null; try { outputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (outputStream != null) { outputStream.flush(); outputStream.close(); } } } } } } }
Post表單
這里需要將注解值改為 RequestMethod.POST,通過 HttpRequestParser.getContentFromBody(httpRequest) 函數可以獲取到表單數據,這里直接檢測表單數據是否為 Json 字符串,是的話則為之多添加一個屬性 :"state" 作為返回值,否則返回只包含屬性 “state” 的 Json 字符串
/** * 作者:leavesC * 時間:2018/4/5 16:30 * 描述:https://github.com/leavesC/AndroidServer */ public class JsonHandler implements RequestHandler { @RequestMapping(method = {RequestMethod.POST}) @Override public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException { String content = HttpRequestParser.getContentFromBody(httpRequest); JSONObject jsonObject = null; try { jsonObject = new JSONObject(content); } catch (JSONException e) { e.printStackTrace(); } if (jsonObject == null) { jsonObject = new JSONObject(); } try { jsonObject.put("state", "success"); } catch (JSONException e) { e.printStackTrace(); } StringEntity stringEntity = new StringEntity(jsonObject.toString(), "utf-8"); httpResponse.setStatusCode(200); httpResponse.setEntity(stringEntity); } }
這里在 Postman 這個工具上進行 Post 操作
以上三個例子都是在電腦端調用的,這和在手機端調用是同個效果的
基本的操作就介紹到這里,再具體的內容可以看示例代碼:AndroidServer
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。