├── app ├── .gitignore ├── debug.jks ├── src │ ├── main │ │ ├── assets │ │ │ └── web │ │ │ │ ├── image │ │ │ │ └── logo.png │ │ │ │ ├── css │ │ │ │ └── login.css │ │ │ │ ├── index.html │ │ │ │ ├── login.html │ │ │ │ └── register.html │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── xml │ │ │ │ └── network_security_config.xml │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── arrays.xml │ │ │ │ ├── styles.xml │ │ │ │ ├── styles_widget.xml │ │ │ │ └── strings.xml │ │ │ ├── layout │ │ │ │ ├── adapter_item_simple_list_2.xml │ │ │ │ ├── fragment_server_manage.xml │ │ │ │ ├── fragment_server_test.xml │ │ │ │ ├── fragment_file_upload.xml │ │ │ │ ├── fragment_main.xml │ │ │ │ └── fragment_user_info_manage.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_upload.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── xuexiang │ │ │ │ ├── server │ │ │ │ ├── api │ │ │ │ │ ├── request │ │ │ │ │ │ └── PageQuery.java │ │ │ │ │ ├── response │ │ │ │ │ │ └── LoginInfo.java │ │ │ │ │ └── base │ │ │ │ │ │ ├── ApiException.java │ │ │ │ │ │ └── ApiResult.java │ │ │ │ ├── controller │ │ │ │ │ ├── PageController.java │ │ │ │ │ ├── FileController.java │ │ │ │ │ └── UserController.java │ │ │ │ ├── OnServerStatusListener.java │ │ │ │ ├── component │ │ │ │ │ ├── AppConfig.java │ │ │ │ │ ├── AppExceptionResolver.java │ │ │ │ │ ├── LoggerInterceptor.java │ │ │ │ │ ├── AppMessageConverter.java │ │ │ │ │ └── LoginInterceptor.java │ │ │ │ ├── ServerConfig.java │ │ │ │ ├── utils │ │ │ │ │ ├── ApiUtils.java │ │ │ │ │ ├── StorageUtils.java │ │ │ │ │ └── TokenUtils.java │ │ │ │ ├── service │ │ │ │ │ ├── impl │ │ │ │ │ │ └── UserServiceImpl.java │ │ │ │ │ └── UserService.java │ │ │ │ ├── CoreService.java │ │ │ │ ├── model │ │ │ │ │ └── User.java │ │ │ │ └── ServerManager.java │ │ │ │ └── templateandserver │ │ │ │ ├── activity │ │ │ │ └── MainActivity.java │ │ │ │ ├── core │ │ │ │ ├── http │ │ │ │ │ ├── loader │ │ │ │ │ │ ├── MiniProgressLoaderFactory.java │ │ │ │ │ │ ├── IProgressLoaderFactory.java │ │ │ │ │ │ ├── ProgressLoader.java │ │ │ │ │ │ └── MiniLoadingDialogLoader.java │ │ │ │ │ ├── callback │ │ │ │ │ │ ├── NoTipCallBack.java │ │ │ │ │ │ ├── TipCallBack.java │ │ │ │ │ │ └── TipProgressLoadingCallBack.java │ │ │ │ │ ├── subscriber │ │ │ │ │ │ ├── NoTipRequestSubscriber.java │ │ │ │ │ │ ├── TipRequestSubscriber.java │ │ │ │ │ │ └── TipProgressLoadingSubscriber.java │ │ │ │ │ └── TestApi.java │ │ │ │ ├── SimpleListAdapter.java │ │ │ │ ├── BaseActivity.java │ │ │ │ └── BaseContainerFragment.java │ │ │ │ ├── utils │ │ │ │ ├── Utils.java │ │ │ │ ├── service │ │ │ │ │ └── JsonSerializationService.java │ │ │ │ ├── NetUtils.java │ │ │ │ ├── sdkinit │ │ │ │ │ ├── UMengInit.java │ │ │ │ │ └── XBasicLibInit.java │ │ │ │ └── XToastUtils.java │ │ │ │ ├── MyApp.java │ │ │ │ ├── db │ │ │ │ ├── InternalDataBase.java │ │ │ │ └── ExternalDataBase.java │ │ │ │ ├── adapter │ │ │ │ └── UserManageAdapter.java │ │ │ │ └── fragment │ │ │ │ ├── net │ │ │ │ ├── RegisterTestFragment.java │ │ │ │ ├── EditUserTestFragment.java │ │ │ │ └── FileUploadFragment.java │ │ │ │ └── manage │ │ │ │ ├── RegisterFragment.java │ │ │ │ ├── EditUserFragment.java │ │ │ │ └── ServerManageFragment.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── xuexiang │ │ │ └── templateandserver │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── xuexiang │ │ └── templateandserver │ │ └── ExampleInstrumentedTest.java ├── channel ├── multiple-channel.gradle ├── x-library-server.gradle └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── renovate.json ├── .idea └── copyright │ ├── profiles_settings.xml │ └── xuexiang.xml ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /app/debug.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/debug.jks -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/assets/web/image/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/assets/web/image/logo.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuexiangjys/TemplateAndServer/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/assets/web/css/login.css: -------------------------------------------------------------------------------- 1 | .sec_body { color:#404040;background:#EBEBEB;text-shadow:#ddd 0 1px 0px;font-family:Helvetica;line-height:1.5;font-size:small; } 2 | .center_father {color:#404040;text-align: center;} 3 | .center_son { margin-right: auto; margin-left: auto; } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 28 16:23:16 CST 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /app/channel: -------------------------------------------------------------------------------- 1 | # 美团 2 | meituan 3 | # 三星 4 | samsungapps 5 | # 小米 6 | xiaomi 7 | # 91助手 8 | 91com 9 | # 魅族 10 | meizu 11 | # 豌豆荚 12 | wandou 13 | # Google Play 14 | googleplay 15 | # 百度 16 | baidu 17 | # 360 18 | 360cn 19 | # 应用宝 20 | myapp 21 | # 华为 22 | huawei 23 | # 蒲公英 24 | pgyer 25 | github -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /LocalRepository 4 | /keystores 5 | /local.properties 6 | /.idea/caches 7 | /.idea/codeStyles 8 | /.idea/inspectionProfiles 9 | /.idea/libraries 10 | /.idea/dictionaries 11 | /.idea/markdown-navigator 12 | /.idea/*.xml 13 | .DS_Store 14 | /build 15 | /captures 16 | .externalNativeBuild -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/multiple-channel.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'walle' 2 | 3 | walle { 4 | // 指定渠道包的输出路径 5 | apkOutputFolder = new File("${project.buildDir}/outputs/channels") 6 | // 定制渠道包的APK的文件名称 7 | apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk' 8 | // 渠道配置文件 9 | channelFile = new File("${project.getProjectDir()}/channel") 10 | } -------------------------------------------------------------------------------- /app/src/test/java/com/xuexiang/templateandserver/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.templateandserver; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/assets/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | AndServer Sample 8 | 11 | 12 | 13 |
14 |
15 |

服务正在运行中...

16 | 点击注册   点击登录 17 |
18 | 19 | -------------------------------------------------------------------------------- /.idea/copyright/xuexiang.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #299EE3 4 | #299EE3 5 | #299EE3 6 | 7 | 8 | 9 | @color/xui_config_color_white 10 | @color/xui_config_color_red 11 | @color/colorAccent 12 | #388E3C 13 | @color/xui_config_color_waring 14 | #353A3E 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xuexiang/templateandserver/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.templateandserver; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.runner.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.xuexiang.templateproject", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 24dp 21 | 20dp 22 | 10dp 23 | 5dp 24 | 10dp 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | # 是否打包APK,打正式包时请设置为true,使用正式的签名 16 | isNeedPackage=false 17 | # 是否使用booster优化APK,这里需要注意gradle的版本,对于最新的gradle版本可能存在兼容问题 18 | isUseBooster=false 19 | android.precompileDependenciesResources=false 20 | 21 | android.useAndroidX=true 22 | android.enableJetifier=true 23 | 24 | android.enableD8=true 25 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 未知 24 | 25 | 26 | 27 | 修改 28 | 删除 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/api/request/PageQuery.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.server.api.request; 2 | 3 | import com.xuexiang.xutil.net.JsonUtil; 4 | 5 | /** 6 | * @author xuexiang 7 | * @since 2018/8/15 上午12:26 8 | */ 9 | public class PageQuery { 10 | 11 | /** 12 | * 第几页数 13 | */ 14 | public int pageNum; 15 | /** 16 | * 每页的数量 17 | */ 18 | public int pageSize; 19 | 20 | public PageQuery() { 21 | } 22 | 23 | public PageQuery(int pageNum, int pageSize) { 24 | this.pageNum = pageNum; 25 | this.pageSize = pageSize; 26 | } 27 | 28 | public int getPageNum() { 29 | return pageNum; 30 | } 31 | 32 | public PageQuery setPageNum(int pageNum) { 33 | this.pageNum = pageNum; 34 | return this; 35 | } 36 | 37 | public int getPageSize() { 38 | return pageSize; 39 | } 40 | 41 | public PageQuery setPageSize(int pageSize) { 42 | this.pageSize = pageSize; 43 | return this; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return JsonUtil.toJson(this); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/controller/PageController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.xuexiang.server.controller; 17 | 18 | import com.yanzhenjie.andserver.annotation.Controller; 19 | import com.yanzhenjie.andserver.annotation.GetMapping; 20 | 21 | /** 22 | * Web页面服务 23 | * 24 | * @author xuexiang 25 | * @since 2020/8/30 3:52 AM 26 | */ 27 | @Controller 28 | public class PageController { 29 | 30 | @GetMapping(path = "/") 31 | public String index() { 32 | // Equivalent to [return "/index"]. 33 | return "forward:/index.html"; 34 | } 35 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/OnServerStatusListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server; 19 | 20 | /** 21 | * 服务状态监听 22 | * 23 | * @author xuexiang 24 | * @since 2020/8/30 3:01 AM 25 | */ 26 | public interface OnServerStatusListener { 27 | 28 | /** 29 | * 服务开启 30 | * 31 | * @param ip 服务器的地址 32 | */ 33 | void onServerStart(String ip); 34 | 35 | /** 36 | * 服务出错 37 | * 38 | * @param message 出错信息 39 | */ 40 | void onServerError(String message); 41 | 42 | /** 43 | * 服务停止 44 | */ 45 | void onServerStop(); 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.activity; 19 | 20 | import android.os.Bundle; 21 | 22 | import com.xuexiang.templateandserver.core.BaseActivity; 23 | import com.xuexiang.templateandserver.fragment.MainFragment; 24 | 25 | /** 26 | * 程序入口,空壳容器 27 | * 28 | * @author xuexiang 29 | * @since 2019-07-07 23:53 30 | */ 31 | public class MainActivity extends BaseActivity { 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | openPage(MainFragment.class); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/api/response/LoginInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server.api.response; 19 | 20 | import com.xuexiang.server.model.User; 21 | 22 | /** 23 | * 登录信息 24 | * 25 | * @author xuexiang 26 | * @since 2018/8/6 下午6:14 27 | */ 28 | public class LoginInfo { 29 | 30 | private User user; 31 | 32 | private String token; 33 | 34 | public User getUser() { 35 | return user; 36 | } 37 | 38 | public LoginInfo setUser(User user) { 39 | this.user = user; 40 | return this; 41 | } 42 | 43 | public String getToken() { 44 | return token; 45 | } 46 | 47 | public LoginInfo setToken(String token) { 48 | this.token = token; 49 | return this; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/loader/MiniProgressLoaderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.loader; 19 | 20 | import android.content.Context; 21 | 22 | import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader; 23 | 24 | /** 25 | * 迷你加载框创建工厂 26 | * 27 | * @author xuexiang 28 | * @since 2019-11-18 23:23 29 | */ 30 | public class MiniProgressLoaderFactory implements IProgressLoaderFactory { 31 | 32 | @Override 33 | public IProgressLoader create(Context context) { 34 | return new MiniLoadingDialogLoader(context); 35 | } 36 | 37 | @Override 38 | public IProgressLoader create(Context context, String message) { 39 | return new MiniLoadingDialogLoader(context, message); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/utils/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.utils; 19 | 20 | import android.content.Intent; 21 | import android.net.Uri; 22 | 23 | import androidx.fragment.app.Fragment; 24 | 25 | /** 26 | * 工具类 27 | * 28 | * @author xuexiang 29 | * @since 2020/8/30 3:27 AM 30 | */ 31 | public final class Utils { 32 | 33 | private Utils() { 34 | throw new UnsupportedOperationException("u can't instantiate me..."); 35 | } 36 | 37 | /** 38 | * 以系统API的方式请求浏览器 39 | * 40 | * @param url 41 | */ 42 | public static void goWeb(Fragment fragment, final String url) { 43 | Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); 44 | fragment.startActivity(intent); 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/loader/IProgressLoaderFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.loader; 19 | 20 | import android.content.Context; 21 | 22 | import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader; 23 | 24 | /** 25 | * IProgressLoader的创建工厂实现接口 26 | * 27 | * @author xuexiang 28 | * @since 2019-11-18 23:17 29 | */ 30 | public interface IProgressLoaderFactory { 31 | 32 | 33 | /** 34 | * 创建进度加载者 35 | * 36 | * @param context 37 | * @return 38 | */ 39 | IProgressLoader create(Context context); 40 | 41 | 42 | /** 43 | * 创建进度加载者 44 | * 45 | * @param context 46 | * @param message 默认提示 47 | * @return 48 | */ 49 | IProgressLoader create(Context context, String message); 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/assets/web/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sign In 10 | 11 | 12 | 13 |
14 |

Sign In

15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 |
LoginName:  
    
Password:  
    
36 | 37 |
40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/assets/web/register.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Register 10 | 11 | 12 | 13 |
14 |

Register

15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 38 | 39 |
LoginName:  
    
Password:  
    
36 | 37 |
40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 16 | 17 | 18 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/adapter_item_simple_list_2.xml: -------------------------------------------------------------------------------- 1 | 17 | 26 | 27 | 31 | 32 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/api/base/ApiException.java: -------------------------------------------------------------------------------- 1 | package com.xuexiang.server.api.base; 2 | 3 | /** 4 | * 错误信息实体 5 | * 6 | * @author xuexiang 7 | * @since 2020/8/30 10:51 PM 8 | */ 9 | public class ApiException extends Exception { 10 | 11 | /** 12 | * 错误的code码 13 | */ 14 | private int mCode; 15 | 16 | public ApiException(String message, int code) { 17 | super(message); 18 | mCode = code; 19 | } 20 | 21 | public ApiException(Throwable e, int code) { 22 | super(e); 23 | mCode = code; 24 | } 25 | 26 | public int getCode() { 27 | return mCode; 28 | } 29 | 30 | /** 31 | * 约定异常 32 | */ 33 | public static class ERROR { 34 | 35 | /** 36 | * Token失效,需要重新获取token的code码 37 | */ 38 | public static final int TOKEN_INVALID = 100; 39 | /** 40 | * 缺少Token 41 | */ 42 | public static final int TOKEN_MISSING = TOKEN_INVALID + 1; 43 | /** 44 | * 认证失败 45 | */ 46 | public static final int AUTH_ERROR = TOKEN_MISSING + 1; 47 | 48 | 49 | /** 50 | * 未知错误 51 | */ 52 | public static final int UNKNOWN = 5000; 53 | 54 | /** 55 | * 一般性业务错误 56 | */ 57 | public static final int COMMON_BUSINESS_ERROR = UNKNOWN + 1; 58 | 59 | /** 60 | * 文件存储失败 61 | */ 62 | public static final int FILE_STORE_ERROR = COMMON_BUSINESS_ERROR + 1; 63 | 64 | /** 65 | * 请求超出限制 66 | */ 67 | public static final int REQUEST_BEYOND_LIMIT = FILE_STORE_ERROR + 1; 68 | 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/controller/FileController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server.controller; 19 | 20 | import com.xuexiang.server.utils.StorageUtils; 21 | import com.yanzhenjie.andserver.annotation.PostMapping; 22 | import com.yanzhenjie.andserver.annotation.RequestMapping; 23 | import com.yanzhenjie.andserver.annotation.RequestParam; 24 | import com.yanzhenjie.andserver.annotation.RestController; 25 | import com.yanzhenjie.andserver.http.multipart.MultipartFile; 26 | 27 | import java.io.File; 28 | import java.io.IOException; 29 | 30 | /** 31 | * @author xuexiang 32 | * @since 2020/9/6 12:37 AM 33 | */ 34 | @RestController 35 | @RequestMapping(path = "/file") 36 | public class FileController { 37 | 38 | @PostMapping(path = "/upload") 39 | String upload(@RequestParam(name = "file") MultipartFile file, @RequestParam(name = "type") String type) throws IOException { 40 | File localFile = StorageUtils.createRandomFile(file, type); 41 | file.transferTo(localFile); 42 | return StorageUtils.getServerSaveFile(localFile); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TemplateAndServer 2 | 3 | 简化版的Android服务端模版,用于接口模拟测试。 4 | 5 | ## 关于我 6 | 7 | [![github](https://img.shields.io/badge/GitHub-xuexiangjys-blue.svg)](https://github.com/xuexiangjys) [![csdn](https://img.shields.io/badge/CSDN-xuexiangjys-green.svg)](http://blog.csdn.net/xuexiangjys) [![简书](https://img.shields.io/badge/简书-xuexiangjys-red.svg)](https://www.jianshu.com/u/6bf605575337) [![掘金](https://img.shields.io/badge/掘金-xuexiangjys-brightgreen.svg)](https://juejin.im/user/598feef55188257d592e56ed) [![知乎](https://img.shields.io/badge/知乎-xuexiangjys-violet.svg)](https://www.zhihu.com/people/xuexiangjys) 8 | 9 | ## 演示(请star支持) 10 | 11 | ### 服务端演示 12 | 13 | ![](https://z3.ax1x.com/2021/06/15/2HmX0x.gif) 14 | 15 | ### 浏览器演示 16 | 17 | ![](https://z3.ax1x.com/2021/06/15/2Hmj76.gif) 18 | 19 | ### 写法对比 20 | 21 | * AndServer 22 | 23 | ![](https://z3.ax1x.com/2021/06/15/2HnC1H.png) 24 | 25 | ![](https://z3.ax1x.com/2021/06/15/2HnPcd.png) 26 | 27 | * SpringBoot 28 | 29 | ![](https://z3.ax1x.com/2021/06/15/2Hn99e.png) 30 | 31 | 从上面的图片我们很容易看出,AndServer的写法和SpringBoot是非常相似的,就连项目工程的结构也是相似的。 32 | 33 | --- 34 | 35 | ## 功能介绍 36 | 37 | > 本项目使用[AndServer](https://github.com/yanzhenjie/AndServer)提供的服务搭建。 38 | 39 | * 统一的请求日志记录。 40 | 41 | * 全局异常捕获处理,返回统一API结果。 42 | 43 | * 增加全局权限验证拦截器。 44 | 45 | * 文件上传。 46 | 47 | * 后台管理界面。 48 | 49 | * 接口测试界面。 50 | 51 | ## 返回Json格式 52 | 53 | ``` 54 | { 55 | "code":0, //响应码,0为成功,否则失败 56 | "msg":"", //请求失败的原因说明 57 | "data":{} //返回的数据对象 58 | } 59 | ``` 60 | 61 | ## 使用方式 62 | 63 | ### 服务器配置 64 | 65 | 在`com.xuexiang.server.ServerConfig`进行配置的修改。 66 | 67 | ### 服务接口编写 68 | 69 | 1.在`com.xuexiang.server.controller`包下创建Controller类。 70 | 71 | 2.在Controller类上加上`@RestController`和`@RequestMapping`注解。 72 | 73 | ### 日志查看 74 | 75 | 在logcat上搜索关键词"AndServer"即可查看请求日志。 76 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles_widget.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 33 | 34 | 35 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/callback/NoTipCallBack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.callback; 19 | 20 | import com.xuexiang.xhttp2.callback.SimpleCallBack; 21 | import com.xuexiang.xhttp2.exception.ApiException; 22 | import com.xuexiang.xhttp2.model.XHttpRequest; 23 | import com.xuexiang.xutil.common.StringUtils; 24 | import com.xuexiang.xutil.common.logger.Logger; 25 | 26 | /** 27 | * 不带错误提示的网络请求回调 28 | * 29 | * @author xuexiang 30 | * @since 2019-11-18 23:02 31 | */ 32 | public abstract class NoTipCallBack extends SimpleCallBack { 33 | 34 | /** 35 | * 记录一下请求的url,确定出错的请求是哪个请求 36 | */ 37 | private String mUrl; 38 | 39 | public NoTipCallBack() { 40 | 41 | } 42 | 43 | public NoTipCallBack(XHttpRequest req) { 44 | this(req.getUrl()); 45 | } 46 | 47 | public NoTipCallBack(String url) { 48 | mUrl = url; 49 | } 50 | 51 | @Override 52 | public void onError(ApiException e) { 53 | if (!StringUtils.isEmpty(mUrl)) { 54 | Logger.e("网络请求的url:" + mUrl, e); 55 | } else { 56 | Logger.e(e); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/subscriber/NoTipRequestSubscriber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.subscriber; 19 | 20 | import com.xuexiang.xhttp2.exception.ApiException; 21 | import com.xuexiang.xhttp2.model.XHttpRequest; 22 | import com.xuexiang.xhttp2.subsciber.BaseSubscriber; 23 | import com.xuexiang.xutil.common.StringUtils; 24 | import com.xuexiang.xutil.common.logger.Logger; 25 | 26 | /** 27 | * 不带错误toast提示的网络请求订阅,只存储错误的日志 28 | * 29 | * @author xuexiang 30 | * @since 2019-11-18 23:11 31 | */ 32 | public abstract class NoTipRequestSubscriber extends BaseSubscriber { 33 | 34 | /** 35 | * 记录一下请求的url,确定出错的请求是哪个请求 36 | */ 37 | private String mUrl; 38 | 39 | public NoTipRequestSubscriber() { 40 | 41 | } 42 | 43 | public NoTipRequestSubscriber(XHttpRequest req) { 44 | this(req.getUrl()); 45 | } 46 | 47 | public NoTipRequestSubscriber(String url) { 48 | mUrl = url; 49 | } 50 | 51 | @Override 52 | public void onError(ApiException e) { 53 | if (!StringUtils.isEmpty(mUrl)) { 54 | Logger.e("网络请求的url:" + mUrl, e); 55 | } else { 56 | Logger.e(e); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/component/AppConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2019 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.xuexiang.server.component; 17 | 18 | import android.content.Context; 19 | 20 | import com.xuexiang.server.ServerConfig; 21 | import com.xuexiang.xutil.file.FileUtils; 22 | import com.yanzhenjie.andserver.annotation.Config; 23 | import com.yanzhenjie.andserver.framework.config.Multipart; 24 | import com.yanzhenjie.andserver.framework.config.WebConfig; 25 | import com.yanzhenjie.andserver.framework.website.AssetsWebsite; 26 | 27 | /** 28 | * web页面配置 29 | * 30 | * @author xuexiang 31 | * @since 2020/8/30 3:51 AM 32 | */ 33 | @Config 34 | public class AppConfig implements WebConfig { 35 | 36 | @Override 37 | public void onConfig(Context context, Delegate delegate) { 38 | delegate.addWebsite(new AssetsWebsite(context, ServerConfig.WEB_ASSENTS)); 39 | 40 | delegate.setMultipart(Multipart.newBuilder() 41 | .allFileMaxSize(ServerConfig.Upload.ALL_FILE_MAX_SIZE) 42 | .fileMaxSize(ServerConfig.Upload.SINGLE_FILE_MAX_SIZE) 43 | .maxInMemorySize(ServerConfig.Upload.MAX_IN_MEMORY_SIZE) 44 | .uploadTempDir(FileUtils.getFileByPath(FileUtils.getDiskCacheDir(ServerConfig.Upload.CACHE_DIR))) 45 | .build()); 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/callback/TipCallBack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.callback; 19 | 20 | import com.xuexiang.templateandserver.utils.XToastUtils; 21 | import com.xuexiang.xhttp2.callback.SimpleCallBack; 22 | import com.xuexiang.xhttp2.exception.ApiException; 23 | import com.xuexiang.xhttp2.model.XHttpRequest; 24 | import com.xuexiang.xutil.common.StringUtils; 25 | import com.xuexiang.xutil.common.logger.Logger; 26 | 27 | /** 28 | * 带错误toast提示的网络请求回调 29 | * 30 | * @author xuexiang 31 | * @since 2019-11-18 23:02 32 | */ 33 | public abstract class TipCallBack extends SimpleCallBack { 34 | 35 | /** 36 | * 记录一下请求的url,确定出错的请求是哪个请求 37 | */ 38 | private String mUrl; 39 | 40 | public TipCallBack() { 41 | 42 | } 43 | 44 | public TipCallBack(XHttpRequest req) { 45 | this(req.getUrl()); 46 | } 47 | 48 | public TipCallBack(String url) { 49 | mUrl = url; 50 | } 51 | 52 | @Override 53 | public void onError(ApiException e) { 54 | XToastUtils.error(e); 55 | if (!StringUtils.isEmpty(mUrl)) { 56 | Logger.e("网络请求的url:" + mUrl, e); 57 | } else { 58 | Logger.e(e); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/utils/service/JsonSerializationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.utils.service; 19 | 20 | import android.content.Context; 21 | 22 | import com.xuexiang.xrouter.annotation.Router; 23 | import com.xuexiang.xrouter.facade.service.SerializationService; 24 | import com.xuexiang.xutil.net.JsonUtil; 25 | 26 | import java.lang.reflect.Type; 27 | 28 | /** 29 | * @author XUE 30 | * @since 2019/3/27 16:39 31 | */ 32 | @Router(path = "/service/json") 33 | public class JsonSerializationService implements SerializationService { 34 | /** 35 | * 对象序列化为json 36 | * 37 | * @param instance obj 38 | * @return json string 39 | */ 40 | @Override 41 | public String object2Json(Object instance) { 42 | return JsonUtil.toJson(instance); 43 | } 44 | 45 | /** 46 | * json反序列化为对象 47 | * 48 | * @param input json string 49 | * @param clazz object type 50 | * @return instance of object 51 | */ 52 | @Override 53 | public T parseObject(String input, Type clazz) { 54 | return JsonUtil.fromJson(input, clazz); 55 | } 56 | 57 | /** 58 | * 进程初始化的方法 59 | * 60 | * @param context 上下文 61 | */ 62 | @Override 63 | public void init(Context context) { 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_server_manage.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 24 | 25 | 32 | 33 | 36 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/subscriber/TipRequestSubscriber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.subscriber; 19 | 20 | 21 | import androidx.annotation.NonNull; 22 | 23 | import com.xuexiang.templateandserver.utils.XToastUtils; 24 | import com.xuexiang.xhttp2.exception.ApiException; 25 | import com.xuexiang.xhttp2.model.XHttpRequest; 26 | import com.xuexiang.xhttp2.subsciber.BaseSubscriber; 27 | import com.xuexiang.xutil.common.StringUtils; 28 | import com.xuexiang.xutil.common.logger.Logger; 29 | 30 | /** 31 | * 带错误toast提示的网络请求订阅 32 | * 33 | * @author xuexiang 34 | * @since 2019-11-18 23:10 35 | */ 36 | public abstract class TipRequestSubscriber extends BaseSubscriber { 37 | /** 38 | * 记录一下请求的url,确定出错的请求是哪个请求 39 | */ 40 | private String mUrl; 41 | 42 | public TipRequestSubscriber() { 43 | 44 | } 45 | 46 | public TipRequestSubscriber(@NonNull XHttpRequest req) { 47 | this(req.getUrl()); 48 | } 49 | 50 | public TipRequestSubscriber(String url) { 51 | mUrl = url; 52 | } 53 | 54 | 55 | @Override 56 | public void onError(ApiException e) { 57 | XToastUtils.error(e); 58 | if (!StringUtils.isEmpty(mUrl)) { 59 | Logger.e("网络请求的url:" + mUrl, e); 60 | } else { 61 | Logger.e(e); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/MyApp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver; 19 | 20 | import android.app.Application; 21 | import android.content.Context; 22 | 23 | import androidx.multidex.MultiDex; 24 | 25 | import com.xuexiang.templateandserver.utils.sdkinit.UMengInit; 26 | import com.xuexiang.templateandserver.utils.sdkinit.XBasicLibInit; 27 | import com.xuexiang.xormlite.annotation.DataBase; 28 | import com.xuexiang.xormlite.enums.DataBaseType; 29 | 30 | /** 31 | * @author xuexiang 32 | * @since 2018/11/7 下午1:12 33 | */ 34 | @DataBase(name = "AndServer", type = DataBaseType.EXTERNAL, path = "/storage/emulated/0/AndServer/databases") 35 | public class MyApp extends Application { 36 | 37 | @Override 38 | protected void attachBaseContext(Context base) { 39 | super.attachBaseContext(base); 40 | //解决4.x运行崩溃的问题 41 | MultiDex.install(this); 42 | } 43 | 44 | @Override 45 | public void onCreate() { 46 | super.onCreate(); 47 | initLibs(); 48 | } 49 | 50 | /** 51 | * 初始化基础库 52 | */ 53 | private void initLibs() { 54 | XBasicLibInit.init(this); 55 | UMengInit.init(this); 56 | } 57 | 58 | 59 | /** 60 | * @return 当前app是否是调试开发模式 61 | */ 62 | public static boolean isDebug() { 63 | return BuildConfig.DEBUG; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/loader/ProgressLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.loader; 19 | 20 | import android.content.Context; 21 | 22 | import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader; 23 | 24 | /** 25 | * 创建进度加载者 26 | * 27 | * @author xuexiang 28 | * @since 2019-07-02 12:51 29 | */ 30 | public final class ProgressLoader { 31 | 32 | private ProgressLoader() { 33 | throw new UnsupportedOperationException("u can't instantiate me..."); 34 | } 35 | 36 | private static IProgressLoaderFactory sIProgressLoaderFactory = new MiniProgressLoaderFactory(); 37 | 38 | public static void setIProgressLoaderFactory(IProgressLoaderFactory sIProgressLoaderFactory) { 39 | ProgressLoader.sIProgressLoaderFactory = sIProgressLoaderFactory; 40 | } 41 | 42 | /** 43 | * 创建进度加载者 44 | * 45 | * @param context 46 | * @return 47 | */ 48 | public static IProgressLoader create(Context context) { 49 | return sIProgressLoaderFactory.create(context); 50 | } 51 | 52 | /** 53 | * 创建进度加载者 54 | * 55 | * @param context 56 | * @param message 默认提示信息 57 | * @return 58 | */ 59 | public static IProgressLoader create(Context context, String message) { 60 | return sIProgressLoaderFactory.create(context, message); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/TestApi.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http; 19 | 20 | import com.xuexiang.server.model.User; 21 | import com.xuexiang.xhttp2.annotation.NetMethod; 22 | import com.xuexiang.xhttp2.model.ApiResult; 23 | 24 | import io.reactivex.Observable; 25 | import retrofit2.http.Body; 26 | import retrofit2.http.Headers; 27 | import retrofit2.http.POST; 28 | 29 | /** 30 | * @author xuexiang 31 | * @since 2020/9/5 11:19 PM 32 | */ 33 | public final class TestApi { 34 | 35 | 36 | public interface UserService { 37 | 38 | /** 39 | * 这里使用的是retrofit的接口定义 40 | */ 41 | @POST("/user/registerUser/") 42 | @Headers({"Content-Type: application/json", "Accept: application/json"}) 43 | Observable> register(@Body User user); 44 | 45 | /** 46 | * 这里使用的是retrofit的接口定义 47 | */ 48 | @POST("/user/editUser/") 49 | @Headers({"Content-Type: application/json", "Accept: application/json"}) 50 | Observable> editUser(@Body User user); 51 | 52 | /** 53 | * 这里使用的是自定义的接口定义 54 | * 55 | * @param userId 用户id 56 | */ 57 | @NetMethod(parameterNames = {"Id"}, url = "/user/deleteUser/", accessToken = false) 58 | Observable deleteUser(long userId); 59 | 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/ServerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server; 19 | 20 | import com.xuexiang.constant.MemoryConstants; 21 | 22 | /** 23 | * 服务器配置 24 | * 25 | * @author xuexiang 26 | * @since 2020/8/30 2:51 AM 27 | */ 28 | public final class ServerConfig { 29 | 30 | private ServerConfig() { 31 | throw new UnsupportedOperationException("u can't instantiate me..."); 32 | } 33 | 34 | /** 35 | * web页面服务资源的加载路径 36 | */ 37 | public static final String WEB_ASSENTS = "/web"; 38 | 39 | /** 40 | * 服务器端口 41 | */ 42 | public static final int SERVER_PORT = 8080; 43 | 44 | /** 45 | * 服务器响应超时时间(秒) 46 | */ 47 | public static final int SERVER_TIMEOUT = 10; 48 | 49 | 50 | /** 51 | * 文件上传配置 52 | */ 53 | public static final class Upload { 54 | /** 55 | * 文件上传的缓存目录 56 | */ 57 | public static final String CACHE_DIR = "_server_upload_cache_"; 58 | 59 | /** 60 | * 一次上传的所有文件的最大大小 61 | */ 62 | public static final int ALL_FILE_MAX_SIZE = MemoryConstants.MB * 20; 63 | 64 | /** 65 | * 一次上传的单个文件的最大大小 66 | */ 67 | public static final int SINGLE_FILE_MAX_SIZE = MemoryConstants.MB * 5; 68 | 69 | /** 70 | * 上传文件写入磁盘前读取的缓存池大小 71 | */ 72 | public static final int MAX_IN_MEMORY_SIZE = MemoryConstants.KB * 10; 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/component/AppExceptionResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.xuexiang.server.component; 17 | 18 | import androidx.annotation.NonNull; 19 | 20 | import com.xuexiang.server.api.base.ApiException; 21 | import com.xuexiang.server.utils.ApiUtils; 22 | import com.yanzhenjie.andserver.annotation.Resolver; 23 | import com.yanzhenjie.andserver.error.BasicException; 24 | import com.yanzhenjie.andserver.framework.ExceptionResolver; 25 | import com.yanzhenjie.andserver.framework.body.JsonBody; 26 | import com.yanzhenjie.andserver.http.HttpRequest; 27 | import com.yanzhenjie.andserver.http.HttpResponse; 28 | import com.yanzhenjie.andserver.util.StatusCode; 29 | 30 | /** 31 | * 应用服务错误信息处理 32 | * 33 | * @author xuexiang 34 | * @since 2020/8/30 11:04 PM 35 | */ 36 | @Resolver 37 | public class AppExceptionResolver implements ExceptionResolver { 38 | 39 | @Override 40 | public void onResolve(@NonNull HttpRequest request, @NonNull HttpResponse response, @NonNull Throwable e) { 41 | e.printStackTrace(); 42 | int code = StatusCode.SC_INTERNAL_SERVER_ERROR; 43 | if (e instanceof BasicException) { 44 | // 基础框架的错误 45 | code = ((BasicException) e).getStatusCode(); 46 | } else if (e instanceof ApiException) { 47 | // 自定义的错误 48 | code = ((ApiException) e).getCode(); 49 | } 50 | String body = ApiUtils.failedJson(code, e.getMessage()); 51 | response.setBody(new JsonBody(body)); 52 | } 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/component/LoggerInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.xuexiang.server.component; 17 | 18 | import androidx.annotation.NonNull; 19 | 20 | import com.xuexiang.xutil.common.logger.Logger; 21 | import com.xuexiang.xutil.net.JsonUtil; 22 | import com.yanzhenjie.andserver.annotation.Interceptor; 23 | import com.yanzhenjie.andserver.framework.HandlerInterceptor; 24 | import com.yanzhenjie.andserver.framework.handler.RequestHandler; 25 | import com.yanzhenjie.andserver.http.HttpMethod; 26 | import com.yanzhenjie.andserver.http.HttpRequest; 27 | import com.yanzhenjie.andserver.http.HttpResponse; 28 | import com.yanzhenjie.andserver.util.MultiValueMap; 29 | 30 | /** 31 | * 日志拦截器 32 | * 33 | * @author xuexiang 34 | * @since 2020/8/30 10:37 PM 35 | */ 36 | @Interceptor 37 | public class LoggerInterceptor implements HandlerInterceptor { 38 | private static final String TAG = "AndServer"; 39 | 40 | @Override 41 | public boolean onIntercept(@NonNull HttpRequest request, @NonNull HttpResponse response, 42 | @NonNull RequestHandler handler) { 43 | String path = request.getPath(); 44 | HttpMethod method = request.getMethod(); 45 | MultiValueMap valueMap = request.getParameter(); 46 | Logger.iTag(TAG, "---------->|开始请求接口: " + path); 47 | Logger.iTag(TAG, " |请求方式: " + method.value()); 48 | Logger.iTag(TAG, " |请求参数: " + JsonUtil.toJson(valueMap)); 49 | return false; 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | TemplateAndServer 3 | 4 | 5 | 启动服务器 6 | 停止服务器 7 | 在浏览器中打开 8 | 后台管理 9 | 接口测试 10 | 11 | 服务器停止了 12 | 没有获取到服务器IP地址 13 | 14 | 15 | ^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(16[6])|(17[0,1,3,5-8])|(18[0-9])|(19[8,9]))\\d{8}$ 16 | ^(?:(?=.*[a-zA-Z])(?=.*[0-9])).{8,18}$ 17 | 密码必须是8~18位字母和数字的组合! 18 | 无效的手机号! 19 | 请输入登录密码 20 | 密码 21 | 请输入登录名 22 | 登录名 23 | 请输入姓名 24 | 姓名 25 | 请输入年龄 26 | 年龄 27 | 性别 28 | 请输入手机号码 29 | 手机号码 30 | 年龄必须大于0小于150! 31 | ^(?:[1-9]\\d?|1[0-4]\\d|150)$ 32 | 选项 33 | 提醒 34 | 请确认连接的服务器地址: 35 | 取消 36 | 继续 37 | 请输入服务器的地址 38 | 地址输入错误 39 | 选择文件 40 | 上传文件路径: 41 | 服务器保存路径: 42 | 上传文件 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/db/InternalDataBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xuexiang.templateandserver.db; 18 | 19 | import android.database.sqlite.SQLiteDatabase; 20 | 21 | import com.j256.ormlite.support.ConnectionSource; 22 | import com.xuexiang.xormlite.AppDataBaseTable; 23 | import com.xuexiang.xormlite.db.DataBaseUtils; 24 | import com.xuexiang.xormlite.db.IDatabase; 25 | import com.xuexiang.xormlite.logs.DBLog; 26 | 27 | import java.sql.SQLException; 28 | 29 | /** 30 | * 应用内部数据库 实现接口 31 | * 32 | * @author xuexiang 33 | * @since 2020/8/31 12:30 AM 34 | */ 35 | public class InternalDataBase implements IDatabase { 36 | /** 37 | * 数据库创建 38 | * 39 | * @param database SQLite数据库 40 | * @param connectionSource 数据库连接 41 | */ 42 | @Override 43 | public void onCreate(SQLiteDatabase database, ConnectionSource connectionSource) { 44 | try { 45 | DataBaseUtils.createTablesByClassNames(connectionSource, AppDataBaseTable.getTables()); 46 | } catch (SQLException e) { 47 | DBLog.e(e); 48 | } 49 | } 50 | 51 | /** 52 | * 数据库升级和降级操作 53 | * 54 | * @param database SQLite数据库 55 | * @param connectionSource 数据库连接 56 | * @param oldVersion 旧版本 57 | * @param newVersion 新版本 58 | */ 59 | @Override 60 | public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) { 61 | DBLog.i("数据库旧版本:" + oldVersion); 62 | DBLog.i("数据库新版本:" + newVersion); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 44 | 45 | 46 | 49 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/component/AppMessageConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Zhenjie Yan. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.xuexiang.server.component; 17 | 18 | import androidx.annotation.NonNull; 19 | import androidx.annotation.Nullable; 20 | 21 | import com.xuexiang.server.utils.ApiUtils; 22 | import com.xuexiang.xutil.net.JsonUtil; 23 | import com.yanzhenjie.andserver.annotation.Converter; 24 | import com.yanzhenjie.andserver.framework.MessageConverter; 25 | import com.yanzhenjie.andserver.framework.body.JsonBody; 26 | import com.yanzhenjie.andserver.http.ResponseBody; 27 | import com.yanzhenjie.andserver.util.IOUtils; 28 | import com.yanzhenjie.andserver.util.MediaType; 29 | 30 | import java.io.IOException; 31 | import java.io.InputStream; 32 | import java.lang.reflect.Type; 33 | import java.nio.charset.Charset; 34 | 35 | /** 36 | * 应用消息解析器 37 | * 38 | * @author xuexiang 39 | * @since 2020/8/30 10:40 PM 40 | */ 41 | @Converter 42 | public class AppMessageConverter implements MessageConverter { 43 | 44 | @Override 45 | public ResponseBody convert(@NonNull Object output, @Nullable MediaType mediaType) { 46 | return new JsonBody(ApiUtils.successfulJson(output)); 47 | } 48 | 49 | @Nullable 50 | @Override 51 | public T convert(@NonNull InputStream stream, @Nullable MediaType mediaType, Type type) throws IOException { 52 | Charset charset = mediaType == null ? null : mediaType.getCharset(); 53 | if (charset == null) { 54 | return JsonUtil.fromJson(IOUtils.toString(stream), type); 55 | } 56 | return JsonUtil.fromJson(IOUtils.toString(stream, charset), type); 57 | } 58 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/adapter/UserManageAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.adapter; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | import com.xuexiang.server.model.User; 23 | import com.xuexiang.templateandserver.R; 24 | import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; 25 | import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; 26 | 27 | /** 28 | * @author xuexiang 29 | * @since 2020/9/5 4:51 PM 30 | */ 31 | public class UserManageAdapter extends BaseRecyclerAdapter { 32 | 33 | private boolean mIsShowPassword; 34 | 35 | public UserManageAdapter() { 36 | this(true); 37 | } 38 | 39 | public UserManageAdapter(boolean isShowPassword) { 40 | mIsShowPassword = isShowPassword; 41 | } 42 | 43 | @Override 44 | protected int getItemLayoutId(int viewType) { 45 | return R.layout.adapter_user_list_item; 46 | } 47 | 48 | @Override 49 | protected void bindData(@NonNull RecyclerViewHolder holder, int position, User item) { 50 | if (item == null) { 51 | return; 52 | } 53 | holder.text(R.id.tv_user_id, String.valueOf(item.getId())); 54 | holder.text(R.id.tv_login_name, item.getLoginName()); 55 | holder.text(R.id.tv_password, mIsShowPassword ? item.getPassword() : "****"); 56 | holder.text(R.id.tv_user_name, item.getName()); 57 | holder.text(R.id.tv_age, String.valueOf(item.getAge())); 58 | holder.text(R.id.tv_gender, item.getGenderName()); 59 | holder.text(R.id.tv_phone, item.getPhone()); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/callback/TipProgressLoadingCallBack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.callback; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | import com.xuexiang.templateandserver.core.BaseFragment; 23 | import com.xuexiang.templateandserver.utils.XToastUtils; 24 | import com.xuexiang.xhttp2.callback.ProgressLoadingCallBack; 25 | import com.xuexiang.xhttp2.exception.ApiException; 26 | import com.xuexiang.xhttp2.model.XHttpRequest; 27 | import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader; 28 | import com.xuexiang.xutil.common.StringUtils; 29 | import com.xuexiang.xutil.common.logger.Logger; 30 | 31 | /** 32 | * 带错误toast提示和加载进度条的网络请求回调 33 | * 34 | * @author xuexiang 35 | * @since 2019-11-18 23:16 36 | */ 37 | public abstract class TipProgressLoadingCallBack extends ProgressLoadingCallBack { 38 | /** 39 | * 记录一下请求的url,确定出错的请求是哪个请求 40 | */ 41 | private String mUrl; 42 | 43 | public TipProgressLoadingCallBack(BaseFragment fragment) { 44 | super(fragment.getProgressLoader()); 45 | } 46 | 47 | public TipProgressLoadingCallBack(IProgressLoader iProgressLoader) { 48 | super(iProgressLoader); 49 | } 50 | 51 | public TipProgressLoadingCallBack(@NonNull XHttpRequest req, IProgressLoader iProgressLoader) { 52 | this(req.getUrl(), iProgressLoader); 53 | } 54 | 55 | public TipProgressLoadingCallBack(String url, IProgressLoader iProgressLoader) { 56 | super(iProgressLoader); 57 | mUrl = url; 58 | } 59 | 60 | @Override 61 | public void onError(ApiException e) { 62 | super.onError(e); 63 | XToastUtils.error(e); 64 | if (!StringUtils.isEmpty(mUrl)) { 65 | Logger.e("网络请求的url:" + mUrl, e); 66 | } else { 67 | Logger.e(e); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/http/subscriber/TipProgressLoadingSubscriber.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core.http.subscriber; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | import com.xuexiang.templateandserver.core.BaseFragment; 23 | import com.xuexiang.templateandserver.utils.XToastUtils; 24 | import com.xuexiang.xhttp2.exception.ApiException; 25 | import com.xuexiang.xhttp2.model.XHttpRequest; 26 | import com.xuexiang.xhttp2.subsciber.ProgressLoadingSubscriber; 27 | import com.xuexiang.xhttp2.subsciber.impl.IProgressLoader; 28 | import com.xuexiang.xutil.common.StringUtils; 29 | import com.xuexiang.xutil.common.logger.Logger; 30 | 31 | /** 32 | * 带错误toast提示和加载进度条的网络请求订阅 33 | * 34 | * @author xuexiang 35 | * @since 2019-11-18 23:11 36 | */ 37 | public abstract class TipProgressLoadingSubscriber extends ProgressLoadingSubscriber { 38 | 39 | /** 40 | * 记录一下请求的url,确定出错的请求是哪个请求 41 | */ 42 | private String mUrl; 43 | 44 | public TipProgressLoadingSubscriber() { 45 | super(); 46 | } 47 | 48 | public TipProgressLoadingSubscriber(BaseFragment fragment) { 49 | super(fragment.getProgressLoader()); 50 | } 51 | 52 | public TipProgressLoadingSubscriber(IProgressLoader iProgressLoader) { 53 | super(iProgressLoader); 54 | } 55 | 56 | public TipProgressLoadingSubscriber(@NonNull XHttpRequest req) { 57 | this(req.getUrl()); 58 | } 59 | 60 | public TipProgressLoadingSubscriber(String url) { 61 | super(); 62 | mUrl = url; 63 | } 64 | 65 | @Override 66 | public void onError(ApiException e) { 67 | super.onError(e); 68 | XToastUtils.error(e); 69 | if (!StringUtils.isEmpty(mUrl)) { 70 | Logger.e("网络请求的url:" + mUrl, e); 71 | } else { 72 | Logger.e(e); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/utils/ApiUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server.utils; 19 | 20 | import androidx.annotation.NonNull; 21 | 22 | import com.xuexiang.server.api.base.ApiException; 23 | import com.xuexiang.server.api.base.ApiResult; 24 | import com.xuexiang.xutil.net.JsonUtil; 25 | 26 | /** 27 | * 接口工具类 28 | * 29 | * @author xuexiang 30 | * @since 2020/8/30 10:56 PM 31 | */ 32 | public final class ApiUtils { 33 | 34 | private ApiUtils() { 35 | throw new UnsupportedOperationException("u can't instantiate me..."); 36 | } 37 | 38 | /** 39 | * 获取出错返回 40 | * 41 | * @param ex 错误信息实体 42 | * @return 出错返回 43 | */ 44 | public static ApiResult error(@NonNull ApiException ex) { 45 | ApiResult apiResult = new ApiResult(); 46 | apiResult.setError(ex.getCode(), ex.getMessage()); 47 | return apiResult; 48 | } 49 | 50 | /** 51 | * 获取出错返回 52 | * 53 | * @param code 错误码 54 | * @param msg 错误信息 55 | * @return 出错返回 56 | */ 57 | public static ApiResult error(int code, String msg) { 58 | ApiResult apiResult = new ApiResult(); 59 | apiResult.setError(code, msg); 60 | return apiResult; 61 | } 62 | 63 | /** 64 | * Business is successful. 65 | * 66 | * @param data return data. 67 | * @return json. 68 | */ 69 | public static String successfulJson(T data) { 70 | ApiResult apiResult = new ApiResult<>(); 71 | apiResult.setData(data); 72 | return JsonUtil.toJson(apiResult); 73 | } 74 | 75 | /** 76 | * Business is failed. 77 | * 78 | * @param code error code. 79 | * @param message message. 80 | * @return json. 81 | */ 82 | public static String failedJson(int code, String message) { 83 | return JsonUtil.toJson(error(code, message)); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server.service.impl; 19 | 20 | import com.xuexiang.server.model.User; 21 | import com.xuexiang.server.service.UserService; 22 | import com.xuexiang.xormlite.AndServerDataBaseRepository; 23 | import com.xuexiang.xormlite.db.DBService; 24 | 25 | import java.sql.SQLException; 26 | import java.util.List; 27 | 28 | /** 29 | * 用户服务实现类 30 | * 31 | * @author xuexiang 32 | * @since 2020/8/31 12:42 AM 33 | */ 34 | public class UserServiceImpl implements UserService { 35 | 36 | private DBService mService; 37 | 38 | public UserServiceImpl() { 39 | mService = AndServerDataBaseRepository.getInstance().getDataBase(User.class); 40 | } 41 | 42 | @Override 43 | public boolean addUser(User user) throws SQLException { 44 | return mService.insert(user) > 0; 45 | } 46 | 47 | @Override 48 | public boolean deleteUser(int userId) throws SQLException { 49 | return mService.deleteById(userId) > 0; 50 | } 51 | 52 | @Override 53 | public boolean updateUser(User record) throws SQLException { 54 | return mService.updateData(record) > 0; 55 | } 56 | 57 | @Override 58 | public List findAllUser(int pageNum, int pageSize) throws SQLException { 59 | return mService.queryPage(pageNum, pageSize, User.KEY_ID, true); 60 | } 61 | 62 | @Override 63 | public List findAllUser() throws SQLException { 64 | return mService.queryAll(); 65 | } 66 | 67 | @Override 68 | public User findUserByAccount(String loginName) throws SQLException { 69 | return mService.queryForColumnFirst(User.KEY_LOGIN_NAME, loginName); 70 | } 71 | 72 | @Override 73 | public User login(String loginName, String password) throws SQLException { 74 | return mService.queryForColumnFirst(User.KEY_LOGIN_NAME, loginName, User.KEY_PASSWORD, password); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/server/service/UserService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.server.service; 19 | 20 | 21 | import com.xuexiang.server.model.User; 22 | 23 | import java.sql.SQLException; 24 | import java.util.List; 25 | 26 | /** 27 | * 用户服务 28 | * 29 | * @author xuexiang 30 | * @since 2020/8/31 12:36 AM 31 | */ 32 | public interface UserService { 33 | 34 | /** 35 | * 添加用户 36 | * 37 | * @param user 用户 38 | * @return 是否成功 39 | * @throws SQLException 数据库执行报错 40 | */ 41 | boolean addUser(User user) throws SQLException; 42 | 43 | /** 44 | * 删除用户 45 | * 46 | * @param userId 用户id 47 | * @return 是否成功 48 | * @throws SQLException 数据库执行报错 49 | */ 50 | boolean deleteUser(int userId) throws SQLException; 51 | 52 | /** 53 | * 更新用户 54 | * 55 | * @param record 用户最新信息 56 | * @return 是否更新成功 57 | * @throws SQLException 数据库执行报错 58 | */ 59 | boolean updateUser(User record) throws SQLException; 60 | 61 | /** 62 | * 分页查询所有用户信息 63 | * 64 | * @param pageNum 页号 65 | * @param pageSize 一页的数量 66 | * @return 指定页面的用户信息 67 | * @throws SQLException 数据库执行报错 68 | */ 69 | List findAllUser(int pageNum, int pageSize) throws SQLException; 70 | 71 | /** 72 | * 查询所有用户信息 73 | * 74 | * @return 所有用户信息 75 | * @throws SQLException 数据库执行报错 76 | */ 77 | List findAllUser() throws SQLException; 78 | 79 | /** 80 | * 根据账户名找到用户信息 81 | * 82 | * @param loginName 登录名 83 | * @return 用户信息 84 | * @throws SQLException 数据库执行报错 85 | */ 86 | User findUserByAccount(String loginName) throws SQLException; 87 | 88 | /** 89 | * 用户登陆 90 | * 91 | * @param loginName 登录名 92 | * @param password 密码 93 | * @return 用户信息 94 | * @throws SQLException 数据库执行报错 95 | */ 96 | User login(String loginName, String password) throws SQLException; 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_server_test.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 23 | 24 | 33 | 34 | 37 | 38 | 44 | 45 | 46 | 47 | 48 | 49 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/x-library-server.gradle: -------------------------------------------------------------------------------- 1 | //引用XAOP插件 2 | apply plugin: 'com.xuexiang.xaop' 3 | //引用XRouter-plugin插件实现自动注册 4 | apply plugin: 'com.xuexiang.xrouter' 5 | 6 | //自动添加依赖 7 | project.configurations.each { configuration -> 8 | if (configuration.name == "implementation") { 9 | //为Project加入X-Library依赖 10 | //XUI框架 11 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys:XUI:1.1.7')) 12 | configuration.dependencies.add(getProject().dependencies.create(deps.androidx.appcompat)) 13 | configuration.dependencies.add(getProject().dependencies.create(deps.androidx.recyclerview)) 14 | configuration.dependencies.add(getProject().dependencies.create(deps.androidx.design)) 15 | configuration.dependencies.add(getProject().dependencies.create(deps.glide)) 16 | //XUtil工具类 17 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XUtil:xutil-core:2.0.0')) 18 | //XAOP切片,版本号前带x的是支持androidx的版本 19 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XAOP:xaop-runtime:1.1.0')) 20 | //XPage 21 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XPage:xpage-lib:3.1.1')) 22 | configuration.dependencies.add(getProject().dependencies.create(deps.butterknife.runtime)) 23 | //XRouter 24 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XRouter:xrouter-runtime:1.0.1')) 25 | //XHttp2 26 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys:XHttp2:2.0.4')) 27 | configuration.dependencies.add(getProject().dependencies.create(deps.rxjava2)) 28 | configuration.dependencies.add(getProject().dependencies.create(deps.rxandroid)) 29 | configuration.dependencies.add(getProject().dependencies.create('com.squareup.okhttp3:okhttp:3.10.0')) 30 | configuration.dependencies.add(getProject().dependencies.create(deps.gson)) 31 | } 32 | 33 | if (configuration.name == "annotationProcessor") { 34 | //XPage 35 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XPage:xpage-compiler:3.1.1')) 36 | configuration.dependencies.add(getProject().dependencies.create(deps.butterknife.compiler)) 37 | //XRouter 38 | configuration.dependencies.add(getProject().dependencies.create('com.github.xuexiangjys.XRouter:xrouter-compiler:1.0.1')) 39 | } 40 | 41 | if (configuration.name == "debugImplementation") { 42 | //内存泄漏监测leak 43 | configuration.dependencies.add(getProject().dependencies.create('com.squareup.leakcanary:leakcanary-android:2.6')) 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/core/SimpleListAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | */ 17 | 18 | package com.xuexiang.templateandserver.core; 19 | 20 | import android.content.Context; 21 | import android.view.View; 22 | import android.widget.TextView; 23 | 24 | import com.xuexiang.templateandserver.R; 25 | import com.xuexiang.xui.adapter.listview.BaseListAdapter; 26 | import com.xuexiang.xutil.common.StringUtils; 27 | 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | /** 32 | * 主副标题显示适配器 33 | * 34 | * @author xuexiang 35 | * @since 2018/12/19 上午12:19 36 | */ 37 | public class SimpleListAdapter extends BaseListAdapter, SimpleListAdapter.ViewHolder> { 38 | 39 | public static final String KEY_TITLE = "title"; 40 | public static final String KEY_SUB_TITLE = "sub_title"; 41 | 42 | public SimpleListAdapter(Context context, List> data) { 43 | super(context, data); 44 | } 45 | 46 | @Override 47 | protected ViewHolder newViewHolder(View convertView) { 48 | ViewHolder holder = new ViewHolder(); 49 | holder.mTvTitle = convertView.findViewById(R.id.tv_title); 50 | holder.mTvSubTitle = convertView.findViewById(R.id.tv_sub_title); 51 | return holder; 52 | } 53 | 54 | @Override 55 | protected int getLayoutId() { 56 | return R.layout.adapter_item_simple_list_2; 57 | } 58 | 59 | @Override 60 | protected void convert(ViewHolder holder, Map item, int position) { 61 | holder.mTvTitle.setText(item.get(KEY_TITLE)); 62 | if (!StringUtils.isEmpty(item.get(KEY_SUB_TITLE))) { 63 | holder.mTvSubTitle.setText(item.get(KEY_SUB_TITLE)); 64 | holder.mTvSubTitle.setVisibility(View.VISIBLE); 65 | } else { 66 | holder.mTvSubTitle.setVisibility(View.GONE); 67 | } 68 | } 69 | 70 | public static class ViewHolder { 71 | /** 72 | * 标题 73 | */ 74 | public TextView mTvTitle; 75 | /** 76 | * 副标题 77 | */ 78 | public TextView mTvSubTitle; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/xuexiang/templateandserver/db/ExternalDataBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.xuexiang.templateandserver.db; 18 | 19 | import android.database.sqlite.SQLiteDatabase; 20 | 21 | import com.j256.ormlite.support.ConnectionSource; 22 | import com.xuexiang.xormlite.db.IExternalDataBase; 23 | import com.xuexiang.xormlite.logs.DBLog; 24 | import com.xuexiang.xutil.file.FileUtils; 25 | 26 | /** 27 | *外部存储的数据库 实现接口 28 | * 29 | * @author xuexiang 30 | * @since 2020/9/6 2:18 AM 31 | */ 32 | public class ExternalDataBase extends InternalDataBase implements IExternalDataBase { 33 | 34 | private int mDatabaseVersion; 35 | private String mDBPath; 36 | private String mDBName; 37 | 38 | public ExternalDataBase(String dbPath, String dbName, int databaseVersion) { 39 | mDBPath = dbPath; 40 | mDBName = dbName; 41 | mDatabaseVersion = databaseVersion; 42 | } 43 | 44 | /** 45 | * 创建或者打开数据库 46 | * 47 | * @param connectionSource 48 | */ 49 | @Override 50 | public void createOrOpenDB(ConnectionSource connectionSource) { 51 | String dbFilePath = FileUtils.getFilePath(mDBPath, mDBName); 52 | if (FileUtils.createOrExistsFile(dbFilePath)) { 53 | SQLiteDatabase db = null; 54 | try { 55 | db = SQLiteDatabase.openOrCreateDatabase(dbFilePath, null); 56 | } catch (Exception e) { 57 | DBLog.e(e); 58 | } 59 | if (db != null) { 60 | int oldVersionCode = db.getVersion(); 61 | //版本不一致需要操作 62 | if (oldVersionCode != mDatabaseVersion) { 63 | if (oldVersionCode == 0) { 64 | onCreate(db, connectionSource); 65 | } else { 66 | if (oldVersionCode < mDatabaseVersion) { 67 | onUpgrade(db, connectionSource, oldVersionCode, mDatabaseVersion); 68 | } 69 | } 70 | } 71 | db.setVersion(mDatabaseVersion); 72 | } 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_file_upload.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 22 | 23 | 28 | 29 | 33 | 34 |