天天看點

搭建Android上的伺服器 “實作隔空取物”的方法

概述

今天逛簡書的時候,發現了一個庫:

https://github.com/MZCretin/WifiTransfer-master

主要功能是這樣的,先口述一下,當打開app,可以通過浏覽器通路一個位址,然後通過浏覽器可以給手機上上傳apk(也支援已有apk删除),然後手機端可以安裝、解除安裝該apk。

三張圖就明白了:

應用啟動後:

搭建Android上的伺服器 “實作隔空取物”的方法

然後PC端通路:

搭建Android上的伺服器 “實作隔空取物”的方法

拖拽apk上傳,即可上傳到手機端。

搭建Android上的伺服器 “實作隔空取物”的方法

ok,大緻介紹清楚了。

注意一定要在同一個網段。

先不談其用處到底有多大,很多時候我看到一個項目的時候,很少考慮其能幹嘛,考慮最多的是它是如何實作的,我會麼,不會那就學,至于能幹嘛,那要等我學會之後?

那麼思考下他的實作,這種上傳檔案的方式,在PC端更加常見,上傳檔案到伺服器。

說到這,就可以想到,可能這個app在手機端搭建了一個伺服器。

恩,沒錯就是這樣的,在手機端搭建了一個伺服器,這樣就可以通過html,将PC端的檔案傳給手機端,然後手機端收到後再同步界面。

同時,也可以将手機上Sdcard上的檔案,完全在PC上呈現。

手機端的Server利用的是該庫:https://github.com/koush/AndroidAsync

解析源碼的事情就不做了,有興趣可以自己學習下,接下來開始正片。

一個群友的問題

之是以會關注到這個庫,是因為在wanandroid群,有個哥們連續問了好久的一個問題,問題是:

如何通過浏覽器輸入一個位址播放手機上的視訊

當時也很多人回答,回答的核心都是正确的。

當然我恰好看到這個庫,之前也沒推送過相關内容,是以我決定寫個簡易的Demo.

當然是Demo就沒有什麼美觀可言了,僅為快速實作效果。

效果圖是這樣的:

搭建Android上的伺服器 “實作隔空取物”的方法

頁面上顯示手機上的視訊清單,然後點選某個視訊,即開始播放該視訊。

有了上例參考,非常簡單。

注:部分代碼直接從上例copy。

該案例需要網絡和Sdcard權限!

先把伺服器搭起來依賴庫

首先,依賴下我們搭建Server需要用到的庫:

compile 'com.koushikdutta.async:androidasync:2.+'           

複制

編寫簡易html

然後我們在assets下編寫一個html檔案用于浏覽器通路,index.html

最簡單的即可:

<!DOCTYPE html 
<html 
<head 
  <meta charset="UTF-8" 
</head 

<body 

嘿嘿嘿,連通了...

</body 

</html            

複制

啟動服務,監聽端口

public class MainActivity extends AppCompatActivity {
  private AsyncHttpServer server = new AsyncHttpServer();
  private AsyncServer mAsyncServer = new AsyncServer();

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    server.get("/", new HttpServerRequestCallback() {
      @Override
      public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
        try {
          response.send(getIndexContent());
        } catch (IOException e) {
          e.printStackTrace();
          response.code(500).end();
        }
      }
    });

    server.listen(mAsyncServer, 54321);

  }

  @Override
  protected void onDestroy() {
    super.onDestroy();

    if (server != null) {
      server.stop();
    }
    if (mAsyncServer != null) {
      mAsyncServer.stop();
    }
  }

  private String getIndexContent() throws IOException {
    BufferedInputStream bInputStream = null;
    try {
      bInputStream = new BufferedInputStream(getAssets().open("index.html"));
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      int len = 0;
      byte[] tmp = new byte[10240];
      while ((len = bInputStream.read(tmp))   0) {
        baos.write(tmp, 0, len);
      }
      return new String(baos.toByteArray(), "utf-8");
    } catch (IOException e) {
      e.printStackTrace();
      throw e;
    } finally {
      if (bInputStream != null) {
        try {
          bInputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}           

複制

可以看到很簡單,建立AsyncHttpServer對象,我們在onCreate中調用get,對外設定一個get型的url監聽,監聽的url是/即根目錄。

然後調用listen,傳入端口号54321,開啟對該端口的監聽。

onDestroy的時候停止伺服器。

當捕獲到對”/”的通路時,讀取assets下的index.html傳回給浏覽器。

記得添加網絡權限。

好了,運作demo,測試一下。

輸入位址,你的手機的IP:端口号。

注意電腦和手機在同一個網段!

然後你應該看到如下效果圖:

搭建Android上的伺服器 “實作隔空取物”的方法

如果沒看到,那不用往下了,先找問題吧~

完善Demo

接下來,我們将手機上的mp4傳回讓其在浏覽器上顯示。

很簡單,既然我們可以監聽/,傳回一個index.html,我們就能監聽另一個url,傳回檔案目錄。

server.get("/files", new HttpServerRequestCallback() {
  @Override
  public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
    JSONArray array = new JSONArray();
    File dir = new File(Environment.getExternalStorageDirectory().getPath());
    String[] fileNames = dir.list();
    if (fileNames != null) {
      for (String fileName : fileNames) {
        File file = new File(dir, fileName);
        if (file.exists() && file.isFile() && file.getName().endsWith(".mp4")) {
          try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", fileName);
            jsonObject.put("path", file.getAbsolutePath());
            array.put(jsonObject);
          } catch (JSONException e) {
            e.printStackTrace();
          }
        }
      }
    }
    response.send(array.toString());
  }
});           

複制

我們監聽/files這個Url,然後傳回Sdcard根目錄的視訊檔案,拼接成JSON傳回。

這裡如果你重新啟動,在浏覽器上輸入:

http://192.168.1.100:54321/files           

複制

會看到一堆JSON資料:

搭建Android上的伺服器 “實作隔空取物”的方法

但是我們需要在剛才的html上顯示,是以這個請求應該是剛才的Html頁面發起:

<!DOCTYPE html 
<html 
<head 
  <meta charset="UTF-8" 
  <script src="jquery-1.7.2.min.js" type="text/javascript" </script 
  <title 文檔的标題</title 
  <script type="text/javascript" 
    $(function() {
      var now = new Date();
      var url = 'files' + '?' + now.getTime();
      // 請求JSON資料
      $.getJSON(url, function(data) {
        // 編輯JSON數組
        for (var i = 0; i < data.length; i++) {
          // 為每個對象生成一個li标簽,添加到頁面的ul中
          var $li = $('<li ' + data[i].name + '</li ');
          $li.attr("path", data[i].path);
          $("#filelist").append($li);

        }
      });
    });
  </script 
</head 
<body 
  <ul id="filelist" style="float:left;" </ul 
</body 
</html            

複制

可能很多朋友沒了解過js,不過應該能看明白,

$.getJSON

擷取傳回的JSON數組,然後周遊為每個Json對象生成一個li标簽,添加到頁面上。

這裡用了jquery,對于js的也需要也請求處理,這裡省略了,很簡單,看源碼即可。

此時通路,已經可以顯示出視訊目錄了:

搭建Android上的伺服器 “實作隔空取物”的方法

接下來就是點選播放了,在html裡面有個标簽叫video用于播放視訊的,他有個src屬性用于設定播放的視訊路徑。

是以我們要做的僅為:

點選名字,拿到該視訊對應的url,然後設定給video的src屬性即可。

那麼視訊的url是什麼?

剛才我們傳回了視訊的路徑,是以我們隻要再監聽一個url,将根據傳入的視訊路徑,将視訊檔案流傳回即可。

server.get("/files/.*", new HttpServerRequestCallback() {
  @Override
  public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
    String path = request.getPath().replace("/files/", "");
    try {
      path = URLDecoder.decode(path, "utf-8");
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    File file = new File(path);
    if (file.exists() && file.isFile()) {
      try {
        FileInputStream fis = new FileInputStream(file);
        response.sendStream(fis, fis.available());
      } catch (Exception e) {
        e.printStackTrace();
      } 
      return;
    }
    response.code(404).send("Not found!");
  }
});           

複制

我們又監聽了一個url為files/xxx.*,捕獲到之後,拿到檔案名,去SDCard找到該檔案,傳回檔案流即可。

html端的代碼為:

<script type="text/javascript" 
  $(function() {
    var now = new Date();
    // 拿到video對象
    var $video = $("#videoplayer");
    var url = 'files' + '?' + now.getTime();
    $.getJSON(url, function(data) {
      for (var i = 0; i < data.length; i++) {
        var $li = $('<li ' + data[i].name + '</li ');
        $li.attr("path", data[i].path);
        $("#filelist").append($li);

        // 點選的時候,擷取路徑,設定給video的src屬性
        $li.click(function() {
          var p = "/files/" + $(this).attr("path");
          $video.attr("src", "/files/" + $(this).attr("path"));
          $video[0].play();
        });
      }
    });
  });
</script            

複制

當然頁面上body标簽内部也多了一個video标簽。

<video id="videoplayer" controls="controls" 
 </video            

複制

到這裡,是以的代碼就介紹完了~~

小結

回頭看,其實就是app中啟動伺服器,監聽一些url,然後針對性的傳回文本、json、檔案流等。

當然了,可以做的時候也挺多的,甚至可以做個PC版本的檔案浏覽器。

可能有很多人對html,js不太熟悉,不過還是建議簡單了解下,或者敲一下本例,因為本例代碼很少,值得作為上手教程。

源碼位址:https://github.com/hongyangAndroid/demo_ShowPhoneMp4

以上就是本文的全部内容,希望對大家的學習有所幫助。