搭建Android上的服务器 “实现隔空取物”

本文已在我的公众号hongyangAndroid原创发布。
你可以在此查看历史文章合集
历史文章合集

概述

今天逛简书的时候,发现了一个库:

主要功能是这样的,先口述一下,当打开app,可以通过浏览器访问一个地址,然后通过浏览器可以给手机上上传apk(也支持已有apk删除),然后手机端可以安装、卸载该apk。

三张图就明白了:

应用启动后:

gekong02.png

然后PC端访问:

gekong01.gif

拖拽apk上传,即可上传到手机端。

gekong03.png

ok,大致介绍清楚了。

注意一定要在同一个网段。

先不谈其用处到底有多大,很多时候我看到一个项目的时候,很少考虑其能干嘛,考虑最多的是它是如何实现的,我会么,不会那就学,至于能干嘛,那要等我学会之后?

那么思考下他的实现,这种上传文件的方式,在PC端更加常见,上传文件到服务器。

说到这,就可以想到,可能这个app在手机端搭建了一个服务器。

恩,没错就是这样的,在手机端搭建了一个服务器,这样就可以通过html,将PC端的文件传给手机端,然后手机端收到后再同步界面。

同时,也可以将手机上Sdcard上的文件,完全在PC上呈现。

手机端的Server利用的是该库:

解析源码的事情就不做了,有兴趣可以自己学习下,接下来开始正片。

一个群友的问题

之所以会关注到这个库,是因为在wanandroid群,有个哥们连续问了好久的一个问题,问题是:

  • 如何通过浏览器输入一个地址播放手机上的视频

当时也很多人回答,回答的核心都是正确的。

当然我恰好看到这个库,之前也没推送过相关内容,所以我决定写个简易的Demo.

当然是Demo就没有什么美观可言了,仅为快速实现效果。

效果图是这样的:

gekong04.gif

页面上显示手机上的视频列表,然后点击某个视频,即开始播放该视频。

有了上例参考,非常简单。

注:部分代码直接从上例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:端口号。

注意电脑和手机在同一个网段!

然后你应该看到如下效果图:

gekong05.png

如果没看到,那不用往下了,先找问题吧~

完善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数据:

gekong06.png

但是我们需要在刚才的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的也需要也请求处理,这里省略了,很简单,看源码即可。

此时访问,已经可以显示出视频目录了:

gekong07.png

接下来就是点击播放了,在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

欢迎关注我的新网站:
http://www.wanandroid.com/index

已标记关键词 清除标记
相关推荐
1 硬件需求 1.1 基本配置 配件 数量 CPU 2核 内存 4G 硬盘 100G 1.2 最低配置 配件 数量 CPU 2核 内存 2G 硬盘 10G 2 软件需求 名称 分类 版本 Windows 操作系统 2003及以上 jdk Java虚拟机 1.5.x及以上 Tomcat Web服务器 5.x及以上 Easy do it (轻松互联网开发平台,简称轻开平台,原名WebEasy) 应用开发服务器 2014及以上 Access 数据库 97及以上 EditPlus 开发工具 2.x及以上 3 软件安装 4 发布 4.1 下载 Easy do it,轻松互联网开发平台(简称轻开平台,原名WebEasy)下载地址: CSDN下载频道:http://download.csdn.net/detail/tx18/8711175 百度云盘:http://pan.baidu.com/s/1eQElpom 官网:http://edoit.htok.net/ 最新更新的下载包:http://download.csdn.net/user/tx18 4.2 发布 复制webeasy目录到D:\下,然后进入%TOMCAT_HOME%\conf目录,用文本编辑器(如:EditPlus)打开server.xml文件,在“Host”标签下添加一“Context”标签: 保存退出并启动tomcat 5 编辑工具 轻开平台可以用任何网页或文本编辑器进行开发,我本人一直在使用EditPlus,以下推荐常用的编辑软件: • EditPlus EditPlus 是一款功能强大的文字处理软件。它可以充分的替换记事本,它也提供网页作家及程序设计师许多强悍的功能。支持 HTML、CSS、PHP、ASP、Perl、C/C++、Java、JavaScript、VBScript 等多种语法的着色显示。程序内嵌网页浏览器,其它功能还包含 FTP 功能、HTML 编辑、URL 突显、自动完成、剪贴文本、行列选择、强大的搜索与替换、多重撤销/重做、拼写检查、自定义快捷键,等等... EditPlus中文版包含在下载包中 6 开发 6.1 第一个json 新建一个扩展名json的文件,如one.json(下图) 然后录入如下内容 {"item":{ 土豆 1.24 KG T恤 68 件 可乐 2.20 瓶 书 51.24 本 @{item:name} @{item:price} @{item:unit} },"sort":@{int:@{item:getSuffix}+1} } 6.2 针对移动App(json格式)的规则及开发例子 除了基本开发标签语言及表达式(参见同一下载包中的开发手册)外,轻开平台特别针对移动App最常用的json文本格式开发的对应规则:  文件扩展名须为json(如:one.json)或用JspEasy扩展  文件内容须为闭合的json格式,静态内容则可直接书写json格式,如: {“item”: { … … },”other”:”other value” }  value属性参数表示输出不带引号的值,如: @{item:price} 输出:"pri
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页