├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── liufengkai.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lfk │ │ └── justwe_webserver │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lfk │ │ │ └── justwe_webserver │ │ │ ├── MainActivity.java │ │ │ └── WebServer │ │ │ ├── ChangeCharset.java │ │ │ ├── Interface │ │ │ ├── OnLogResult.java │ │ │ ├── OnPermissionFile.java │ │ │ ├── OnPostData.java │ │ │ ├── OnWebFileResult.java │ │ │ ├── OnWebResult.java │ │ │ └── OnWebStringResult.java │ │ │ ├── RequestSolve.java │ │ │ ├── Servers.java │ │ │ ├── WebServer.java │ │ │ ├── WebServerDefault.java │ │ │ └── WebServerService.java │ └── res │ │ ├── layout │ │ ├── activity_main.xml │ │ └── content_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lfk │ └── justwe_webserver │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | JustWe-WebServer -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/liufengkai.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | noti 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | 47 | 48 | 49 | 50 | 1.8 51 | 52 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JustWe-WebServer 2 | 3 | Android手机上的Http服务器,可以用于内网/外网的数据交换。 4 | ![logo](https://github.com/lfkdsk/JustWeTools/blob/master/picture/justwe.png) 5 | ps: 这个项目是[JustWeEngine](https://github.com/lfkdsk/JustWeEngine)游戏框架中处理网络事件的一部分。 6 | 7 | ## 如何使用 8 | 9 | 设置as Library或直接将代码拷出,如果使用JustWeEngine可以直接使用Gradle或者Maven构建。 10 | 11 | ## 快速入门 12 | ### 1.添加Service: 13 | 使用前请先添加Service到manifest文件: 14 | 15 | ``` xml 16 | 17 | 18 | 19 | ``` 20 | 21 | ### 2.初始化\打开\关闭: 22 | 23 | ``` java 24 | 25 | private WebServer server; 26 | server = new WebServer(MainActivity.this, new OnLogResult() { 27 | @Override 28 | public void OnResult(String log) { 29 | 30 | } 31 | 32 | @Override 33 | public void OnError(String error) { 34 | 35 | } 36 | }); 37 | server.initWebService(); 38 | 39 | ``` 40 | 41 | 初始化的时候推荐实现一个OnLogResult用于接受log日志和错误。 42 | `OnLogResult`的返回数据是线程安全的,可以直接传送到View中打印出来。 43 | 当然也有其他的构造方法: 44 | ``` java 45 | 46 | public WebServer(Activity engine); 47 | public WebServer(Activity engine, OnLogResult logResult, int webPort); // 端口 48 | 49 | ``` 50 | 初始化之后: 51 | 52 | ``` java 53 | 54 | server.startWebService(); 55 | server.stopWebService(); 56 | 57 | ``` 58 | 59 | 使用该方法打开监听\关闭。 60 | 61 | ### 3.添加路由: 62 | 63 | ``` java 64 | 65 | server.apply("/lfk", new OnWebStringResult() { 66 | @Override 67 | public String OnResult() { 68 | return "======="; 69 | } 70 | }); 71 | 72 | server.apply("/main", new OnWebFileResult() { 73 | @Override 74 | public File returnFile() { 75 | return new File(WebServerDefault.WebServerFiles+"/"+"welcome.html"); 76 | } 77 | }); 78 | 79 | ``` 80 | 可以通过此种方法添加路由,并返回数据或者文件。 81 | 需要表单提交的如Post可以使用如下接口,返回一个HashMap存储key和value。 82 | 83 | ``` java 84 | 85 | server.apply("/lfkdsk", new OnPostData() { 86 | @Override 87 | public String OnPostData(HashMap hashMap) { 88 | String S = hashMap.get("LFKDSK"); 89 | Logger.e(S); 90 | return "=="; 91 | } 92 | }); 93 | 94 | ``` 95 | ### 4.获取/提交数据: 96 | 97 | 向服务器提交数据,只需使用正常的get / post即可。 98 | 99 | ##有问题反馈 100 | 在使用中有任何问题,欢迎反馈给我,可以用以下联系方式跟我交流 101 | 102 | * 邮件:lfk_dsk@hotmail.com 103 | * weibo: [@亦狂亦侠_亦温文](http://www.weibo.com/u/2443510260) 104 | * 博客: [刘丰恺](http://www.cnblogs.com/lfk-dsk/) 105 | 106 | ## License 107 | 108 | Copyright 2015 [刘丰恺](http://www.cnblogs.com/lfk-dsk/) 109 | 110 | Licensed under the Apache License, Version 2.0 (the "License"); 111 | you may not use this file except in compliance with the License. 112 | You may obtain a copy of the License at 113 | 114 | http://www.apache.org/licenses/LICENSE-2.0 115 | 116 | Unless required by applicable law or agreed to in writing, software 117 | distributed under the License is distributed on an "AS IS" BASIS, 118 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 119 | See the License for the specific language governing permissions and 120 | limitations under the License. 121 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.lfk.justwe_webserver" 9 | minSdkVersion 16 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.1.1' 26 | compile 'com.android.support:design:23.1.1' 27 | compile 'com.github.lfkdsk:JustWeEngine:v1.0' 28 | } 29 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/liufengkai/Documents/AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lfk/justwe_webserver/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.FloatingActionButton; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.Toolbar; 7 | import android.util.Log; 8 | import android.view.Menu; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.widget.ScrollView; 12 | import android.widget.TextView; 13 | 14 | import com.lfk.justwe_webserver.WebServer.Interface.OnLogResult; 15 | import com.lfk.justwe_webserver.WebServer.Interface.OnPostData; 16 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebFileResult; 17 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebStringResult; 18 | import com.lfk.justwe_webserver.WebServer.WebServer; 19 | import com.lfk.justwe_webserver.WebServer.WebServerDefault; 20 | import com.lfk.justweengine.Utils.logger.Logger; 21 | 22 | import java.io.File; 23 | import java.util.HashMap; 24 | 25 | public class MainActivity extends AppCompatActivity implements OnLogResult { 26 | private WebServer server; 27 | private TextView textView; 28 | private ScrollView scrollView; 29 | private boolean open = false; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | Logger.init(); 36 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 37 | setSupportActionBar(toolbar); 38 | 39 | textView = (TextView) findViewById(R.id.main_log); 40 | scrollView = (ScrollView) findViewById(R.id.main_scroll); 41 | 42 | server = new WebServer(MainActivity.this, this); 43 | server.initWebService(); 44 | 45 | 46 | server.apply("/lfk", new OnWebStringResult() { 47 | @Override 48 | public String OnResult() { 49 | return "======="; 50 | } 51 | }); 52 | 53 | server.apply("/main", new OnWebFileResult() { 54 | @Override 55 | public File returnFile() { 56 | return new File(WebServerDefault.WebServerFiles + "/" + "welcome.html"); 57 | } 58 | }); 59 | 60 | 61 | server.apply("/lfkdsk", new OnPostData() { 62 | @Override 63 | public String OnPostData(HashMap hashMap) { 64 | String S = hashMap.get("LFKDSK"); 65 | Logger.e(S); 66 | return "=_="; 67 | } 68 | }); 69 | 70 | 71 | FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); 72 | fab.setOnClickListener(new View.OnClickListener() { 73 | @Override 74 | public void onClick(View view) { 75 | if (!open) { 76 | server.startWebService(); 77 | open = true; 78 | } else { 79 | server.stopWebService(); 80 | open = false; 81 | } 82 | } 83 | }); 84 | } 85 | 86 | 87 | @Override 88 | public boolean onCreateOptionsMenu(Menu menu) { 89 | // Inflate the menu; this adds items to the action bar if it is present. 90 | getMenuInflater().inflate(R.menu.menu_main, menu); 91 | return true; 92 | } 93 | 94 | @Override 95 | public boolean onOptionsItemSelected(MenuItem item) { 96 | // Handle action bar item clicks here. The action bar will 97 | // automatically handle clicks on the Home/Up button, so long 98 | // as you specify a parent activity in AndroidManifest.xml. 99 | int id = item.getItemId(); 100 | 101 | //noinspection SimplifiableIfStatement 102 | if (id == R.id.action_settings) { 103 | return true; 104 | } 105 | 106 | return super.onOptionsItemSelected(item); 107 | } 108 | 109 | @Override 110 | public void OnResult(String log) { 111 | Log.e("log", log); 112 | textView.append(log + "\n"); 113 | scrollView.fullScroll(ScrollView.FOCUS_DOWN); 114 | } 115 | 116 | @Override 117 | public void OnError(String error) { 118 | Log.e("error", error); 119 | 120 | } 121 | 122 | @Override 123 | protected void onDestroy() { 124 | super.onDestroy(); 125 | server.callOffWebService(); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/ChangeCharset.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | /** 6 | * 转换字符串的编码 7 | */ 8 | public class ChangeCharset { 9 | /** 10 | * 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁块 11 | */ 12 | public static final String US_ASCII = "US-ASCII"; 13 | 14 | /** 15 | * ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 16 | */ 17 | public static final String ISO_8859_1 = "ISO-8859-1"; 18 | 19 | /** 20 | * 8 位 UCS 转换格式 21 | */ 22 | public static final String UTF_8 = "UTF-8"; 23 | 24 | /** 25 | * 16 位 UCS 转换格式,Big Endian(最低地址存放高位字节)字节顺序 26 | */ 27 | public static final String UTF_16BE = "UTF-16BE"; 28 | 29 | /** 30 | * 16 位 UCS 转换格式,Little-endian(最高地址存放低位字节)字节顺序 31 | */ 32 | public static final String UTF_16LE = "UTF-16LE"; 33 | 34 | /** 35 | * 16 位 UCS 转换格式,字节顺序由可选的字节顺序标记来标识 36 | */ 37 | public static final String UTF_16 = "UTF-16"; 38 | 39 | /** 40 | * 中文超大字符集 41 | */ 42 | public static final String GBK = "GBK"; 43 | 44 | /** 45 | * 将字符编码转换成US-ASCII码 46 | */ 47 | public static String toASCII(String str) throws UnsupportedEncodingException { 48 | return changeCharset(str, US_ASCII); 49 | } 50 | 51 | /** 52 | * 将字符编码转换成ISO-8859-1码 53 | */ 54 | public static String toISO_8859_1(String str) throws UnsupportedEncodingException { 55 | return changeCharset(str, ISO_8859_1); 56 | } 57 | 58 | /** 59 | * 将字符编码转换成UTF-8码 60 | */ 61 | public static String toUTF_8(String str) throws UnsupportedEncodingException { 62 | return changeCharset(str, UTF_8); 63 | } 64 | 65 | /** 66 | * 将字符编码转换成UTF-16BE码 67 | */ 68 | public static String toUTF_16BE(String str) throws UnsupportedEncodingException { 69 | return changeCharset(str, UTF_16BE); 70 | } 71 | 72 | /** 73 | * 将字符编码转换成UTF-16LE码 74 | */ 75 | public static String toUTF_16LE(String str) throws UnsupportedEncodingException { 76 | return changeCharset(str, UTF_16LE); 77 | } 78 | 79 | /** 80 | * 将字符编码转换成UTF-16码 81 | */ 82 | public static String toUTF_16(String str) throws UnsupportedEncodingException { 83 | return changeCharset(str, UTF_16); 84 | } 85 | 86 | /** 87 | * 将字符编码转换成GBK码 88 | */ 89 | public static String toGBK(String str) throws UnsupportedEncodingException { 90 | return changeCharset(str, GBK); 91 | } 92 | 93 | /** 94 | * 字符串编码转换的实现方法 95 | * 96 | * @param str 待转换编码的字符串 97 | * @param newCharset 目标编码 98 | * @return 99 | * @throws UnsupportedEncodingException 100 | */ 101 | public static String changeCharset(String str, String newCharset) 102 | throws UnsupportedEncodingException { 103 | if (str != null) { 104 | //用默认字符编码解码字符串。 105 | byte[] bs = str.getBytes(); 106 | //用新的字符编码生成字符串 107 | return new String(bs, newCharset); 108 | } 109 | return null; 110 | } 111 | 112 | /** 113 | * 字符串编码转换的实现方法 114 | * 115 | * @param str 待转换编码的字符串 116 | * @param oldCharset 原编码 117 | * @param newCharset 目标编码 118 | * @return 119 | * @throws UnsupportedEncodingException 120 | */ 121 | public static String changeCharset(String str, String oldCharset, String newCharset) 122 | throws UnsupportedEncodingException { 123 | if (str != null) { 124 | // 用旧的字符编码解码字符串。解码可能会出现异常。 125 | byte[] bs = str.getBytes(oldCharset); 126 | // 用新的字符编码生成字符串 127 | return new String(bs, newCharset); 128 | } 129 | return null; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnLogResult.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | /** 4 | * Created by liufengkai on 16/1/6. 5 | */ 6 | public interface OnLogResult { 7 | void OnResult(String log); 8 | void OnError(String error); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnPermissionFile.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created by liufengkai on 16/1/14. 7 | */ 8 | public interface OnPermissionFile extends OnWebResult { 9 | File OnPermissionFile(String name); 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnPostData.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * Created by liufengkai on 16/1/14. 7 | */ 8 | public interface OnPostData extends OnWebResult { 9 | String OnPostData(HashMap hashMap); 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnWebFileResult.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created by liufengkai on 16/1/6. 7 | */ 8 | public interface OnWebFileResult extends OnWebResult { 9 | File returnFile(); 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnWebResult.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | /** 4 | * Created by liufengkai on 16/1/6. 5 | */ 6 | public interface OnWebResult { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Interface/OnWebStringResult.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer.Interface; 2 | 3 | /** 4 | * Created by liufengkai on 16/1/14. 5 | */ 6 | public interface OnWebStringResult extends OnWebResult { 7 | String OnResult(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/RequestSolve.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import com.lfk.justwe_webserver.WebServer.Interface.OnPostData; 4 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebFileResult; 5 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebResult; 6 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebStringResult; 7 | 8 | import java.io.BufferedInputStream; 9 | import java.io.BufferedOutputStream; 10 | import java.io.BufferedReader; 11 | import java.io.ByteArrayOutputStream; 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.IOException; 15 | import java.io.InputStreamReader; 16 | import java.io.OutputStream; 17 | import java.net.Socket; 18 | import java.util.HashMap; 19 | 20 | /** 21 | * Solve request 22 | * 23 | * @author liufengkai 24 | * Created by liufengkai on 16/1/14. 25 | */ 26 | public class RequestSolve extends Thread { 27 | private Socket client; 28 | private BufferedReader clientReader; 29 | // url in link 30 | private String url; 31 | private HashMap params; 32 | // private String urlName = ""; 33 | private int type; 34 | 35 | public RequestSolve(Socket s) { 36 | super(); 37 | this.client = s; 38 | 39 | } 40 | 41 | @Override 42 | public void run() { 43 | super.run(); 44 | try { 45 | clientReader = new BufferedReader( 46 | new InputStreamReader(client.getInputStream(), "UTF-8")); 47 | 48 | while (true) { 49 | String s = clientReader.readLine().trim(); 50 | 51 | if (s.equals("")) { 52 | break; 53 | } 54 | 55 | // Logger.e(s + '\n'); 56 | Servers.getLogResult().OnResult(s); 57 | 58 | int httpHeader = s.indexOf(" HTTP/"); 59 | switch (s.substring(0, 4)) { 60 | case "GET ": 61 | // get request link 62 | url = s.substring(4, httpHeader); 63 | Servers.getLogResult().OnResult("visiting" + url); 64 | break; 65 | case "POST": 66 | int last = s.indexOf('?'); 67 | params = new HashMap<>(); 68 | if (last > 0) { 69 | url = s.substring(5, last); 70 | getParams(s.substring(last + 1, httpHeader)); 71 | } else 72 | url = s.substring(5, httpHeader); 73 | break; 74 | } 75 | } 76 | } catch (IOException e) { 77 | e.printStackTrace(); 78 | Servers.getLogResult().OnError(e.getMessage()); 79 | } 80 | 81 | exeResult(url); 82 | } 83 | 84 | private void exeResult(String Url) { 85 | OnWebResult result = WebServer.getRule(Url); 86 | if (result != null) { 87 | if (result instanceof OnWebStringResult) { 88 | returnString(((OnWebStringResult) result).OnResult()); 89 | } else if (result instanceof OnWebFileResult) { 90 | returnFile(((OnWebFileResult) result).returnFile()); 91 | } else if (result instanceof OnPostData) { 92 | returnString(((OnPostData) result).OnPostData(params)); 93 | } 94 | } else { 95 | // 在新的权限管理之前,先允许所有服务器根目录下的文件访问 96 | File file = new File(WebServerDefault.WebServerFiles + Url); 97 | if (file.exists()) { 98 | returnFile(file); 99 | } 100 | } 101 | } 102 | 103 | // private void findChildFile(String Url) { 104 | // int index = Url.lastIndexOf('/'); 105 | // if (index != -1) { 106 | // Log.d("index", Url.lastIndexOf('/') + ""); 107 | // // 仍能逐层递减 108 | // if (index == 0) { 109 | // exeResult("/"); 110 | // urlName = "/" + urlName; 111 | // return; 112 | // } 113 | // 114 | // exeResult(Url.substring(0, index)); 115 | // urlName = Url.substring(index - 1) + urlName; 116 | // } 117 | // Logger.e("Url:" + Url.substring(0, Url.lastIndexOf('/'))); 118 | // Logger.e("UrlName:" + Url.substring(Url.lastIndexOf('/') + 1)); 119 | // } 120 | 121 | private void returnString(String str) { 122 | try { 123 | OutputStream o = client.getOutputStream(); 124 | o.write(setType(getHeaderBase(), str.length(), "200 OK").getBytes()); 125 | for (int i = 0; 126 | i < str.length(); 127 | i++) { 128 | o.write(str.charAt(i)); 129 | } 130 | o.close(); 131 | client.close(); 132 | } catch (IOException e) { 133 | e.printStackTrace(); 134 | } 135 | } 136 | 137 | private void returnFile(File file) { 138 | if (file.exists()) { 139 | try { 140 | BufferedInputStream inputStream = 141 | new BufferedInputStream( 142 | new FileInputStream(file)); 143 | BufferedOutputStream out = new BufferedOutputStream(client.getOutputStream()); 144 | ByteArrayOutputStream tempOut = new ByteArrayOutputStream(); 145 | byte[] buf = new byte[4096]; 146 | int count; 147 | while ((count = inputStream.read(buf)) != -1) { 148 | tempOut.write(buf, 0, count); 149 | } 150 | tempOut.flush(); 151 | out.write(setType(getHeaderBase(), tempOut.size(), "200 OK").getBytes()); 152 | out.write(tempOut.toByteArray()); 153 | out.flush(); 154 | client.close(); 155 | } catch (IOException e) { 156 | e.printStackTrace(); 157 | } 158 | } 159 | } 160 | 161 | private void getParams(String url) { 162 | int valueFirst; 163 | for (String s : url.split("&")) { 164 | valueFirst = s.indexOf("="); 165 | params.put(s.substring(0, valueFirst), 166 | s.substring(valueFirst + 1)); 167 | } 168 | } 169 | 170 | private String getHeaderBase() { 171 | return "HTTP/1.1 %code%\n" + 172 | "Server: JustWe_WebServer/0.1\n" + 173 | "Content-Length: %length%\n" + 174 | "Connection: close\n" + 175 | "Content-Type: text/html; charset=iso-8859-1\n\n"; 176 | } 177 | 178 | private String setType(String str, double length, String TYPE) { 179 | str = str.replace("%code%", TYPE); 180 | str = str.replace("%length%", "" + length); 181 | return str; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/Servers.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.IOException; 6 | import java.net.InetAddress; 7 | import java.net.ServerSocket; 8 | import java.net.Socket; 9 | import java.util.concurrent.ExecutorService; 10 | import java.util.concurrent.Executors; 11 | 12 | /** 13 | * Thread Controller 14 | * 15 | * @author liufengkai 16 | * Created by liufengkai on 16/1/6. 17 | */ 18 | public class Servers extends Thread { 19 | // listen to connect 20 | private ServerSocket serverSocket; 21 | // log / error listener 22 | private static WebServer.MessageHandler logResult; 23 | private Context context; 24 | private boolean IsRunning; 25 | // solve threads 26 | private static ExecutorService exe; 27 | 28 | public Servers(Context context, WebServer.MessageHandler logResult, int port) { 29 | super(); 30 | this.context = context; 31 | Servers.logResult = logResult; 32 | this.IsRunning = true; 33 | exe = Executors.newCachedThreadPool(); 34 | try { 35 | serverSocket = new ServerSocket(port, 0, 36 | InetAddress.getByName(WebServerDefault.WebServerIp)); 37 | logResult.OnResult("listen to :" + WebServerDefault.WebServerIp 38 | + ":" + port); 39 | } catch (IOException e) { 40 | e.printStackTrace(); 41 | logResult.OnError("Server IO error"); 42 | } 43 | } 44 | 45 | @Override 46 | public void run() { 47 | super.run(); 48 | while (IsRunning) { 49 | try { 50 | logResult.OnResult("<<<<<<< waiting >>>>>>>"); 51 | Socket s = serverSocket.accept(); 52 | logResult.OnResult("get from" + s.getInetAddress().toString()); 53 | exe.execute(new RequestSolve(s)); 54 | } catch (IOException e) { 55 | logResult.OnError(e.getMessage()); 56 | } 57 | } 58 | } 59 | 60 | public void stopServer() { 61 | IsRunning = false; 62 | try { 63 | serverSocket.close(); 64 | logResult.OnResult("Server close"); 65 | } catch (IOException e) { 66 | logResult.OnError(e.getMessage()); 67 | } 68 | } 69 | 70 | public static WebServer.MessageHandler getLogResult() { 71 | return logResult; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/WebServer.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.content.ServiceConnection; 8 | import android.os.Handler; 9 | import android.os.IBinder; 10 | import android.os.Message; 11 | 12 | import com.lfk.justwe_webserver.WebServer.Interface.OnLogResult; 13 | import com.lfk.justwe_webserver.WebServer.Interface.OnPermissionFile; 14 | import com.lfk.justwe_webserver.WebServer.Interface.OnWebResult; 15 | import com.lfk.justweengine.Utils.logger.Logger; 16 | 17 | import java.io.File; 18 | import java.util.HashMap; 19 | 20 | /** 21 | * WebServer 22 | * 23 | * @author liufengkai 24 | * Created by liufengkai on 16/1/6. 25 | */ 26 | public class WebServer { 27 | private Activity engine; 28 | private static HashMap webServerRule; 29 | private OnLogResult logResult; 30 | private WebServerService webServerService; 31 | private Integer webPort = null; 32 | private ServiceConnection serviceConnection; 33 | private final int ERROR = -1; 34 | private final int LOG = 1; 35 | 36 | public WebServer(Activity engine) { 37 | this.engine = engine; 38 | init(); 39 | } 40 | 41 | public WebServer(Activity engine, OnLogResult logResult) { 42 | this.engine = engine; 43 | this.logResult = logResult; 44 | init(); 45 | } 46 | 47 | public WebServer(Activity engine, OnLogResult logResult, int webPort) { 48 | this.engine = engine; 49 | this.logResult = logResult; 50 | this.webPort = webPort; 51 | init(); 52 | } 53 | 54 | private void init() { 55 | webServerRule = new HashMap<>(); 56 | 57 | WebServerService.init(engine); 58 | 59 | serviceConnection = new ServiceConnection() { 60 | @Override 61 | public void onServiceConnected(ComponentName name, IBinder service) { 62 | webServerService = ((WebServerService.LocalBinder) service).getService(); 63 | if (logResult != null) 64 | logResult.OnResult(WebServerDefault.WebServerServiceConnected); 65 | } 66 | 67 | @Override 68 | public void onServiceDisconnected(ComponentName name) { 69 | webServerService = null; 70 | if (logResult != null) 71 | logResult.OnResult(WebServerDefault.WebServerServiecDisconnected); 72 | } 73 | }; 74 | 75 | } 76 | 77 | 78 | public void startWebService() { 79 | if (webServerService != null) { 80 | webServerService.startServer(new MessageHandler(), 81 | (webPort == null) ? WebServerDefault.WebDefaultPort : webPort); 82 | } 83 | } 84 | 85 | public void stopWebService() { 86 | if (webServerService != null) { 87 | webServerService.stopServer(); 88 | } 89 | } 90 | 91 | public void initWebService() { 92 | WebServerDefault.init(engine.getApplicationContext()); 93 | // 绑定Service 94 | engine.bindService(new Intent(engine, WebServerService.class), 95 | serviceConnection, 96 | Context.BIND_AUTO_CREATE 97 | ); 98 | } 99 | 100 | public void callOffWebService() { 101 | engine.unbindService(serviceConnection); 102 | } 103 | 104 | public void apply(String rule, OnWebResult result) { 105 | webServerRule.put(rule, result); 106 | } 107 | 108 | public void apply(final String rule) { 109 | webServerRule.put(rule, new OnPermissionFile() { 110 | @Override 111 | public File OnPermissionFile(String name) { 112 | Logger.e(WebServerDefault.WebServerFiles + rule + name); 113 | return new File(WebServerDefault.WebServerFiles + rule + name); 114 | } 115 | }); 116 | } 117 | 118 | public static OnWebResult getRule(String rule) { 119 | return webServerRule.get(rule); 120 | } 121 | 122 | public void setLogResult(OnLogResult logResult) { 123 | this.logResult = logResult; 124 | } 125 | 126 | public class MessageHandler extends Handler { 127 | @Override 128 | public void handleMessage(Message msg) { 129 | super.handleMessage(msg); 130 | switch (msg.what) { 131 | case LOG: 132 | logResult.OnResult(msg.obj.toString()); 133 | break; 134 | case ERROR: 135 | logResult.OnError(msg.obj.toString()); 136 | break; 137 | } 138 | } 139 | 140 | public void OnError(String str) { 141 | Message message = this.obtainMessage(); 142 | message.what = ERROR; 143 | message.obj = str; 144 | sendMessage(message); 145 | } 146 | 147 | public void OnResult(String str) { 148 | Message message = this.obtainMessage(); 149 | message.what = LOG; 150 | message.obj = str; 151 | sendMessage(message); 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/WebServerDefault.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * Created by liufengkai on 16/1/6. 10 | */ 11 | public class WebServerDefault { 12 | 13 | public static final String WebServerFiles = Environment 14 | .getExternalStorageDirectory() + "/JustWeWebServer"; 15 | 16 | public static final String WebServerServiceConnected = "Service connected"; 17 | 18 | public static final String WebServerServiecDisconnected = "Service disconnected"; 19 | 20 | public static final int WebDefaultPort = 8080; 21 | 22 | public static String getWebServerFiles() { 23 | return WebServerFiles; 24 | } 25 | 26 | public static String WebServerIp; 27 | 28 | public static Context context; 29 | 30 | public static void init(Context context) { 31 | WebServerDefault.context = context; 32 | File file = new File(WebServerFiles); 33 | if (!file.exists()) { 34 | file.mkdirs(); 35 | } 36 | } 37 | 38 | /** 39 | * 转换IP 40 | * 41 | * @param i Ip字符串 42 | * @return 字符串 43 | */ 44 | public static String intToIp(int i) { 45 | return ((i) & 0xFF) + "." + 46 | ((i >> 8) & 0xFF) + "." + 47 | ((i >> 16) & 0xFF) + "." + 48 | (i >> 24 & 0xFF); 49 | } 50 | 51 | public static void setWebServerIp(String webServerIp) { 52 | WebServerIp = webServerIp; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/lfk/justwe_webserver/WebServer/WebServerService.java: -------------------------------------------------------------------------------- 1 | package com.lfk.justwe_webserver.WebServer; 2 | 3 | import android.app.Activity; 4 | import android.app.Notification; 5 | import android.app.NotificationManager; 6 | import android.app.PendingIntent; 7 | import android.app.Service; 8 | import android.content.Intent; 9 | import android.net.wifi.SupplicantState; 10 | import android.net.wifi.WifiInfo; 11 | import android.net.wifi.WifiManager; 12 | import android.os.Binder; 13 | import android.os.IBinder; 14 | 15 | import com.lfk.justwe_webserver.R; 16 | 17 | /** 18 | * Service for Android 19 | * 20 | * @author liufengkai 21 | * Created by liufengkai on 16/1/6. 22 | */ 23 | public class WebServerService extends Service { 24 | private WebServer.MessageHandler logResult; 25 | private NotificationManager notificationManager; 26 | private Notification notification; 27 | private final IBinder mBinder = new LocalBinder(); 28 | private Servers webServers; 29 | private static Activity engine; 30 | private PendingIntent contentIntent; 31 | private boolean IsRunning; 32 | 33 | @Override 34 | public void onCreate() { 35 | super.onCreate(); 36 | 37 | notificationManager = (NotificationManager) 38 | getSystemService(NOTIFICATION_SERVICE); 39 | 40 | updateNotification("Open Service"); 41 | } 42 | 43 | public static void init(Activity engine) { 44 | WebServerService.engine = engine; 45 | } 46 | 47 | 48 | @Override 49 | public IBinder onBind(Intent intent) { 50 | return mBinder; 51 | } 52 | 53 | private void updateNotification(String text) { 54 | contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, engine.getClass()), 0); 55 | Notification.Builder builder = new Notification.Builder(engine) 56 | .setContentTitle("WebServer") 57 | .setContentText(text) 58 | .setContentIntent(contentIntent) 59 | .setSmallIcon(R.mipmap.ic_launcher) 60 | .setWhen(System.currentTimeMillis()); 61 | notification = builder.getNotification(); 62 | notificationManager.notify(0, notification); 63 | } 64 | 65 | @Override 66 | public void onDestroy() { 67 | super.onDestroy(); 68 | 69 | } 70 | 71 | public class LocalBinder extends Binder { 72 | WebServerService getService() { 73 | return WebServerService.this; 74 | } 75 | } 76 | 77 | public void startServer(WebServer.MessageHandler logResult, int port) { 78 | this.logResult = logResult; 79 | // running 80 | setIsRunning(true); 81 | 82 | WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); 83 | WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 84 | 85 | WebServerDefault.setWebServerIp(WebServerDefault.intToIp(wifiInfo.getIpAddress())); 86 | // if not in wifi 87 | if (wifiInfo.getSupplicantState() != SupplicantState.COMPLETED) { 88 | this.logResult.OnError("Please connect to a WIFI-network."); 89 | try { 90 | throw new Exception("Please connect to a WIFI-network."); 91 | } catch (Exception e) { 92 | e.printStackTrace(); 93 | } 94 | } 95 | 96 | webServers = new Servers(engine.getApplicationContext(), logResult, port); 97 | webServers.start(); 98 | 99 | updateNotification("running on " + 100 | WebServerDefault.WebServerIp + ":" + port); 101 | } 102 | 103 | public void stopServer() { 104 | setIsRunning(false); 105 | if(webServers != null) { 106 | webServers.stopServer(); 107 | webServers.interrupt(); 108 | } 109 | } 110 | 111 | public void setIsRunning(boolean isRunning) { 112 | IsRunning = isRunning; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 19 | 20 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/JustWe-WebServer/8ba1c8d3a8451e9aed8bc2fcfe3b2f54bf93eb73/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/JustWe-WebServer/8ba1c8d3a8451e9aed8bc2fcfe3b2f54bf93eb73/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/JustWe-WebServer/8ba1c8d3a8451e9aed8bc2fcfe3b2f54bf93eb73/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/JustWe-WebServer/8ba1c8d3a8451e9aed8bc2fcfe3b2f54bf93eb73/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lfkdsk/JustWe-WebServer/8ba1c8d3a8451e9aed8bc2fcfe3b2f54bf93eb73/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | > 2 | 3 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | JustWe-WebServer 3 | Settings 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |