瀏覽代碼

创建

master
Cd苳 3 年之前
當前提交
99584c1ad4
共有 58 個檔案被更改,包括 1904 行新增0 行删除
  1. +15
    -0
      .gitignore
  2. +3
    -0
      .idea/.gitignore
  3. +1
    -0
      .idea/.name
  4. +6
    -0
      .idea/compiler.xml
  5. +20
    -0
      .idea/gradle.xml
  6. +35
    -0
      .idea/jarRepositories.xml
  7. +9
    -0
      .idea/misc.xml
  8. +10
    -0
      .idea/runConfigurations.xml
  9. +6
    -0
      .idea/vcs.xml
  10. +1
    -0
      app/.gitignore
  11. +70
    -0
      app/build.gradle
  12. +21
    -0
      app/proguard-rules.pro
  13. +26
    -0
      app/src/androidTest/java/com/example/tidalairpeisong/ExampleInstrumentedTest.java
  14. +25
    -0
      app/src/main/AndroidManifest.xml
  15. +30
    -0
      app/src/main/java/com/example/tidalairpeisong/App.java
  16. +50
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/bean/PageList.java
  17. +38
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/bean/Response.java
  18. +40
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/error/ErrorInfo.java
  19. +138
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/error/ExceptionHelper.java
  20. +32
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/error/NetWorkError.java
  21. +21
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/error/OnError.java
  22. +18
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/interceptor/InterceptorUtil.java
  23. +81
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/interceptor/TokenInterceptor.java
  24. +59
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/manager/RxHttpManager.java
  25. +67
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/parser/ResponseParser.java
  26. +21
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/url/Api.java
  27. +11
    -0
      app/src/main/java/com/example/tidalairpeisong/rxhttp/url/BaseUrl.java
  28. +210
    -0
      app/src/main/java/com/example/tidalairpeisong/user/bean/MallProductBean.java
  29. +185
    -0
      app/src/main/java/com/example/tidalairpeisong/user/bean/VersionInfo.java
  30. +48
    -0
      app/src/main/java/com/example/tidalairpeisong/user/ui/activity/MainActivity.java
  31. +30
    -0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  32. +170
    -0
      app/src/main/res/drawable/ic_launcher_background.xml
  33. +18
    -0
      app/src/main/res/layout/activity_main.xml
  34. +5
    -0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
  35. +5
    -0
      app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
  36. 二進制
      app/src/main/res/mipmap-hdpi/ic_launcher.png
  37. 二進制
      app/src/main/res/mipmap-hdpi/ic_launcher_round.png
  38. 二進制
      app/src/main/res/mipmap-mdpi/ic_launcher.png
  39. 二進制
      app/src/main/res/mipmap-mdpi/ic_launcher_round.png
  40. 二進制
      app/src/main/res/mipmap-xhdpi/ic_launcher.png
  41. 二進制
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
  42. 二進制
      app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  43. 二進制
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
  44. 二進制
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  45. 二進制
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
  46. +16
    -0
      app/src/main/res/values-night/themes.xml
  47. +10
    -0
      app/src/main/res/values/colors.xml
  48. +8
    -0
      app/src/main/res/values/strings.xml
  49. +16
    -0
      app/src/main/res/values/themes.xml
  50. +5
    -0
      app/src/main/res/xml/network_security_config.xml
  51. +17
    -0
      app/src/test/java/com/example/tidalairpeisong/ExampleUnitTest.java
  52. +26
    -0
      build.gradle
  53. +17
    -0
      gradle.properties
  54. 二進制
      gradle/wrapper/gradle-wrapper.jar
  55. +6
    -0
      gradle/wrapper/gradle-wrapper.properties
  56. +172
    -0
      gradlew
  57. +84
    -0
      gradlew.bat
  58. +2
    -0
      settings.gradle

+ 15
- 0
.gitignore 查看文件

@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

+ 3
- 0
.idea/.gitignore 查看文件

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

+ 1
- 0
.idea/.name 查看文件

@@ -0,0 +1 @@
NewProject

+ 6
- 0
.idea/compiler.xml 查看文件

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
</component>
</project>

+ 20
- 0
.idea/gradle.xml 查看文件

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

+ 35
- 0
.idea/jarRepositories.xml 查看文件

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component>
</project>

+ 9
- 0
.idea/misc.xml 查看文件

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

+ 10
- 0
.idea/runConfigurations.xml 查看文件

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
</project>

+ 6
- 0
.idea/vcs.xml 查看文件

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

+ 1
- 0
app/.gitignore 查看文件

@@ -0,0 +1 @@
/build

+ 70
- 0
app/build.gradle 查看文件

@@ -0,0 +1,70 @@
plugins {
id 'com.android.application'
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.3"

defaultConfig {
applicationId "com.example.tidalairpeisong"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"

multiDexEnabled true

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

javaCompileOptions {
annotationProcessorOptions {
arguments = [
//使用asXxx方法时必须,传入你依赖的RxJava版本
rxhttp_rxjava: '3.1.1',
]
}
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}


}

dependencies {

implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation 'com.github.liujingxing.rxhttp:rxhttp:2.6.8'
annotationProcessor 'com.github.liujingxing.rxhttp:rxhttp-compiler:2.6.8' //生成RxHttp类,纯Java项目,请使用annotationProcessor代替kapt
//rxjava2
// implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
// implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// implementation 'com.github.liujingxing.rxlife:rxlife-rxjava2:2.2.1' //管理RxJava2生命周期,页面销毁,关闭请求

//rxjava3
implementation 'io.reactivex.rxjava3:rxjava:3.1.1'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava3:2.2.1' //管理RxJava3生命周期,页面销毁,关闭请求

implementation 'androidx.multidex:multidex:2.0.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
//日志的拦截器
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.2'
}

+ 21
- 0
app/proguard-rules.pro 查看文件

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

+ 26
- 0
app/src/androidTest/java/com/example/tidalairpeisong/ExampleInstrumentedTest.java 查看文件

@@ -0,0 +1,26 @@
package com.example.tidalairpeisong;

import android.content.Context;

import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.newproject", appContext.getPackageName());
}
}

+ 25
- 0
app/src/main/AndroidManifest.xml 查看文件

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tidalairpeisong">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- 获取网络信息状态,如当前的网络连接是否有效 -->
<application
android:name="com.example.tidalairpeisong.App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/Theme.NewProject">
<activity android:name="com.example.tidalairpeisong.user.ui.activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

+ 30
- 0
app/src/main/java/com/example/tidalairpeisong/App.java 查看文件

@@ -0,0 +1,30 @@
package com.example.tidalairpeisong;

import android.app.Application;
import android.content.Context;

import androidx.multidex.MultiDex;

import com.example.tidalairpeisong.rxhttp.manager.RxHttpManager;

public class App extends Application {

private static App instance;

public static App getInstance() {
return instance;
}

@Override
public void onCreate() {
super.onCreate();
instance = this;
RxHttpManager.init(this);
}

protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}

}

+ 50
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/bean/PageList.java 查看文件

@@ -0,0 +1,50 @@
package com.example.tidalairpeisong.rxhttp.bean;

import java.util.ArrayList;
import java.util.List;

/**
* @ClassName PageList
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public class PageList<T> {

private int curPage; //当前页数
private int pageCount; //总页数
private int total; //总条数
private List<T> datas;

public int getCurPage() {
return curPage;
}

public int getPageCount() {
return pageCount;
}

public int getTotal() {
return total;
}

public List<T> getDatas() {
return datas;
}

public void setCurPage(int curPage) {
this.curPage = curPage;
}

public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}

public void setTotal(int total) {
this.total = total;
}

public void setDatas(ArrayList<T> datas) {
this.datas = datas;
}
}

+ 38
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/bean/Response.java 查看文件

@@ -0,0 +1,38 @@
package com.example.tidalairpeisong.rxhttp.bean;


/**
* User: ljx
* Date: 2018/10/21
* Time: 13:16
*/
public class Response<T> {

private int errorCode;
private String errorMsg;
private T data;

public int getCode() {
return errorCode;
}

public String getMsg() {
return errorMsg;
}

public T getData() {
return data;
}

public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}

public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}

public void setData(T data) {
this.data = data;
}
}

+ 40
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/error/ErrorInfo.java 查看文件

@@ -0,0 +1,40 @@
package com.example.tidalairpeisong.rxhttp.error;

public class ErrorInfo {
private int errorCode;//仅指服务器返回的错误码
private String errorMsg;//错误文案,网络错误、请求失败错误、服务器返回的错误等
private Throwable throwable;//异常信息

public ErrorInfo(Throwable throwable){
this.throwable = throwable;
ExceptionHelper.ResponseException exception = ExceptionHelper.handleException(throwable);
String errorMsg = exception.message;//网络异常
this.errorMsg = errorMsg;
}

public int getErrorCode() {
return errorCode;
}

public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}

public String getErrorMsg() {
return errorMsg;
}

public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}

public Throwable getThrowable() {
return throwable;
}

public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}


}

+ 138
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/error/ExceptionHelper.java 查看文件

@@ -0,0 +1,138 @@
package com.example.tidalairpeisong.rxhttp.error;

import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.net.ConnectException;

import retrofit2.HttpException;
import rxhttp.wrapper.exception.ParseException;

/**
* @ClassName ExceptionHelper
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public class ExceptionHelper {
private static final int UNAUTHORIZED = 401;
private static final int FORBIDDEN = 403;
private static final int NOT_FOUND = 404;
private static final int REQUEST_TIMEOUT = 408;
private static final int INTERNAL_SERVER_ERROR = 500;
private static final int BAD_GATEWAY = 502;
private static final int SERVICE_UNAVAILABLE = 503;
private static final int GATEWAY_TIMEOUT = 504;

public static ResponseException handleException(Throwable e){
//转换成ResponseException,根据状态码判定错误信息
ResponseException ex;
if(e instanceof HttpException){
HttpException httpException=(HttpException)e;
/**0
* 传入状态码,根据状态码判定错误信息
*/
ex=new ResponseException(e,ERROR.HTTP_ERROR);
switch (httpException.code()){
case UNAUTHORIZED:
case FORBIDDEN:
case NOT_FOUND:
case REQUEST_TIMEOUT:
case GATEWAY_TIMEOUT:
case INTERNAL_SERVER_ERROR:
case BAD_GATEWAY:
case SERVICE_UNAVAILABLE:
default:
ex.message = "网络错误";
break;
}
return ex;
} else if (e instanceof ServerException) {
ServerException resultException = (ServerException) e;
ex = new ResponseException(resultException, resultException.code);
ex.message = resultException.message;
return ex;
} else if(e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException){
ex=new ResponseException(e,ERROR.PARSE_ERROR);
ex.message="解析错误";
return ex;
}else if(e instanceof ConnectException){
ex=new ResponseException(e,ERROR.NETWORD_ERROR);
ex.message="连接失败";
return ex;
}else if(e instanceof javax.net.ssl.SSLHandshakeException){
ex=new ResponseException(e,ERROR.SSL_ERROR);
ex.message="证书验证失败";
return ex;
}else {
ex=new ResponseException(e,ERROR.UNKNOWN);
ex.message="未知错误";
return ex;
}
}
/**
* 约定异常
*/
public static class ERROR{
/**
* 自定义异常
*/
private static final int UNAUTHORIZED = 401;//请求用户进行身份验证
private static final int UNREQUEST=403;//服务器理解请求客户端的请求,但是拒绝执行此请求
private static final int UNFINDSOURCE=404;//服务器无法根据客户端的请求找到资源
private static final int SEVERERROR=500;//服务器内部错误,无法完成请求。
/**
* 协议出错
*/
public static final int HTTP_ERROR = 1003;
/**
* 未知错误
*/
public static final int UNKNOWN = 1000;
/**
* 解析错误
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络错误
*/
public static final int NETWORD_ERROR = 1002;
/**
* 证书出错
*/
public static final int SSL_ERROR = 1005;
}
/**
* 自定义Throwable
*/
public static class ResponseThrowable extends Exception{
public int code;
public String message;
public ResponseThrowable(Throwable throwable,int code){
super(throwable);
this.code=code;
}
}
/**
* 服务器异常
*/
public class ServerException extends RuntimeException{
public int code;
public String message;
}

/**
* 统一异常类,便于处理
*/
public static class ResponseException extends Exception{
public int code;
public String message;
public ResponseException (Throwable throwable,int code){
super(throwable);
this.code=code;
}
}
}

+ 32
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/error/NetWorkError.java 查看文件

@@ -0,0 +1,32 @@
package com.example.tidalairpeisong.rxhttp.error;

import android.content.Context;
import android.widget.Toast;

/**
* @ClassName ErrorInfo
* @Description TODO
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public class NetWorkError {
public static void error(Context context,Throwable e){
ExceptionHelper.ResponseException exception = ExceptionHelper.handleException(e);
switch (exception.code) {
case ExceptionHelper.ERROR.UNKNOWN:
case ExceptionHelper.ERROR.PARSE_ERROR:
case ExceptionHelper.ERROR.NETWORD_ERROR:
case ExceptionHelper.ERROR.HTTP_ERROR:
case ExceptionHelper.ERROR.SSL_ERROR:
Toast.makeText(context, exception.message, Toast.LENGTH_SHORT).show();
break;
case -1:
// 跳转到登陆页面
break;
default:
Toast.makeText(context, exception.message, Toast.LENGTH_SHORT).show();
break;
}
}
}

+ 21
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/error/OnError.java 查看文件

@@ -0,0 +1,21 @@
package com.example.tidalairpeisong.rxhttp.error;

import android.os.Build;

import androidx.annotation.RequiresApi;

import io.reactivex.rxjava3.functions.Consumer;


@RequiresApi(api = Build.VERSION_CODES.N)
public interface OnError extends Consumer<Throwable> {
default void accept(Throwable throwable) {
try {
onError(new ErrorInfo(throwable));
} catch (Exception e) {
e.printStackTrace();
}
}

void onError(ErrorInfo error) throws Exception;
}

+ 18
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/interceptor/InterceptorUtil.java 查看文件

@@ -0,0 +1,18 @@
package com.example.tidalairpeisong.rxhttp.interceptor;

import android.util.Log;

import okhttp3.logging.HttpLoggingInterceptor;

public class InterceptorUtil {
//日志拦截器
public static HttpLoggingInterceptor logInterceptor(){
return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.e("日志拦截器", "log: "+message);

}
}).setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印数据的级别
}
}

+ 81
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/interceptor/TokenInterceptor.java 查看文件

@@ -0,0 +1,81 @@
package com.example.tidalairpeisong.rxhttp.interceptor;

import java.io.IOException;
import java.util.HashMap;

import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import rxhttp.wrapper.param.RxHttp;
import rxhttp.wrapper.parse.SimpleParser;

public class TokenInterceptor implements Interceptor {

//token刷新时间
private static volatile long SESSION_KEY_REFRESH_TIME = 0;

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response originalResponse = chain.proceed(request);
String code = originalResponse.header("token_code");
if ("-1".equals(code)) { //token 失效 1、这里根据自己的业务需求写判断条件
return handleTokenInvalid(chain, request);
}
return originalResponse;
}


//处理token失效问题
private Response handleTokenInvalid(Chain chain, Request request) throws IOException {
HashMap<String, String> mapParam = new HashMap<>();
RequestBody body = request.body();
if (body instanceof FormBody) {
FormBody formBody = (FormBody) body;
for (int i = 0; i < formBody.size(); i++) {
mapParam.put(formBody.name(i), formBody.value(i)); //2、保存参数
}
}
//同步刷新token
String requestTime = mapParam.get("request_time"); //3、发请求前需要add("request_time",System.currentTimeMillis())
boolean success = refreshToken(requestTime);
Request newRequest;
if (success) { //刷新成功,重新签名
//mapParam.put("token", User.get().getToken()); //4、拿到最新的token,重新发起请求
newRequest = RxHttp.postForm(request.url().toString())
.addAll(mapParam) //添加参数
.buildRequest();
} else {
newRequest = request;
}
return chain.proceed(newRequest);
}

//刷新token
private boolean refreshToken(Object value) {
long requestTime = 0;
try {
requestTime = Integer.parseInt(value.toString());
} catch (Exception ignore) {
}
//请求时间小于token刷新时间,说明token已经刷新,则无需再次刷新
if (requestTime <= SESSION_KEY_REFRESH_TIME) return true;
synchronized (this) {
//再次判断是否已经刷新
if (requestTime <= SESSION_KEY_REFRESH_TIME) return true;
try {
//获取到最新的token,这里需要同步请求token,千万不能异步 5、根据自己的业务修改
String token = RxHttp.postForm("/refreshToken/...")
.execute(SimpleParser.get(String.class));

SESSION_KEY_REFRESH_TIME = System.currentTimeMillis() / 1000;
//User.get().setToken(token); //保存最新的token
return true;
} catch (IOException e) {
return false;
}
}
}
}

+ 59
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/manager/RxHttpManager.java 查看文件

@@ -0,0 +1,59 @@
package com.example.tidalairpeisong.rxhttp.manager;

import android.app.Application;

import com.example.tidalairpeisong.BuildConfig;
import com.example.tidalairpeisong.rxhttp.interceptor.InterceptorUtil;
import com.example.tidalairpeisong.rxhttp.interceptor.TokenInterceptor;

import java.io.File;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import rxhttp.RxHttpPlugins;
import rxhttp.wrapper.cahce.CacheMode;
import rxhttp.wrapper.cookie.CookieStore;
import rxhttp.wrapper.param.Method;
import rxhttp.wrapper.ssl.HttpsUtils;

public class RxHttpManager {

public static void init(Application context) {
File file = new File(context.getExternalCacheDir(), "RxHttpCookie");
HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
OkHttpClient client = new OkHttpClient.Builder()
.cookieJar(new CookieStore(file))
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager) //添加信任证书
.hostnameVerifier((hostname, session) -> true) //忽略host验证
// .followRedirects(false) //禁制OkHttp的重定向操作,我们自己处理重定向
.addInterceptor(InterceptorUtil.logInterceptor())
.addInterceptor(new TokenInterceptor())
.build();

//设置缓存策略,非必须
File cacheFile = new File(context.getExternalCacheDir(), "RxHttpCache");
//RxHttp初始化,非必须
RxHttpPlugins.init(client) //自定义OkHttpClient对象
.setDebug(BuildConfig.DEBUG) //是否开启调试模式,开启后,logcat过滤RxHttp,即可看到整个请求流程日志
.setCache(cacheFile, 1000 * 100, CacheMode.REQUEST_NETWORK_FAILED_READ_CACHE)
// .setExcludeCacheKeys("time") //设置一些key,不参与cacheKey的组拼
// .setResultDecoder(s -> s) //设置数据解密/解码器,非必须
// .setConverter(FastJsonConverter.create()) //设置全局的转换器,非必须
.setOnParamAssembly(p -> { //设置公共参数,非必须
//1、可根据不同请求添加不同参数,每次发送请求前都会被回调
//2、如果希望部分请求不回调这里,发请求前调用RxHttp#setAssemblyEnabled(false)即可
Method method = p.getMethod();
if (method.isGet()) {
p.add("method", "get");
} else if (method.isPost()) { //Post请求
p.add("method", "post");
}
return p.add("versionName", "1.0.0")//添加公共参数
.add("time", System.currentTimeMillis())
.addHeader("deviceType", "android"); //添加公共请求头
});
}
}

+ 67
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/parser/ResponseParser.java 查看文件

@@ -0,0 +1,67 @@
package com.example.tidalairpeisong.rxhttp.parser;

import com.example.tidalairpeisong.rxhttp.bean.PageList;
import com.example.tidalairpeisong.rxhttp.bean.Response;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.reflect.Type;

import rxhttp.wrapper.annotation.Parser;
import rxhttp.wrapper.exception.ParseException;
import rxhttp.wrapper.parse.AbstractParser;
import rxhttp.wrapper.utils.Converter;

/**
* @ClassName ResponseParser
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
@Parser(name = "Response", wrappers = {PageList.class})
public class ResponseParser<T> extends AbstractParser<T> {

/**
* 此构造方法适用于任意Class对象,但更多用于带泛型的Class对象,如:List<Student>
* <p>
* 用法:
* Java: .asParser(new ResponseParser<List<Student>>(){})
* Kotlin: .asParser(object : ResponseParser<List<Student>>() {})
* <p>
* 注:此构造方法一定要用protected关键字修饰,否则调用此构造方法将拿不到泛型类型
*/
protected ResponseParser() {
super();
}

/**
* 此构造方法仅适用于不带泛型的Class对象,如: Student.class
* <p>
* 用法
* Java: .asParser(new ResponseParser<>(Student.class)) 或者 .asResponse(Student.class)
* Kotlin: .asParser(ResponseParser(Student::class.java)) 或者 .asResponse(Student::class.java)
*/
public ResponseParser(Type type) {
super(type);
}

@SuppressWarnings("unchecked")
@Override
public T onParse(@NotNull okhttp3.Response response) throws IOException {
Response<T> data = Converter.convertTo(response, Response.class, mType);
T t = data.getData(); //获取data字段
if (t == null && mType == String.class) {
/*
* 考虑到有些时候服务端会返回:{"errorCode":0,"errorMsg":"关注成功"} 类似没有data的数据
* 此时code正确,但是data字段为空,直接返回data的话,会报空指针错误,
* 所以,判断泛型为String类型时,重新赋值,并确保赋值不为null
*/
t = (T) data.getMsg();
}
if (data.getCode() != 0 || t == null) {//code不等于0,说明数据不正确,抛出异常
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
}

+ 21
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/url/Api.java 查看文件

@@ -0,0 +1,21 @@
package com.example.tidalairpeisong.rxhttp.url;

/**
* @ClassName Api
* @Description TODO
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public interface Api {
/**
* 版本更新
* */
String version = "/app-versions/versions/index";

/**
* 商城产品列表
* */
String mall_products = "/tiny-shop/v1/product/product/index";

}

+ 11
- 0
app/src/main/java/com/example/tidalairpeisong/rxhttp/url/BaseUrl.java 查看文件

@@ -0,0 +1,11 @@
package com.example.tidalairpeisong.rxhttp.url;

import rxhttp.wrapper.annotation.DefaultDomain;

public class BaseUrl {
//测试地址:http://dev.gas888.com/api/
//正式地址:http://new.gas888.com/api/
@DefaultDomain
public static String baseUrl = "http://new.gas888.com/api";

}

+ 210
- 0
app/src/main/java/com/example/tidalairpeisong/user/bean/MallProductBean.java 查看文件

@@ -0,0 +1,210 @@
package com.example.tidalairpeisong.user.bean;

/**
* @ClassName MallProductBean
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public class MallProductBean {

private String id;
private String name;
private String sketch;
private String keywords;
private String picture;
private String view;
private String match_point;
private String price;
private String market_price;
private String cost_price;
private String stock;
private Integer sales;
private String merchant_id;
private String is_open_presell;
private String is_open_commission;
private String point_exchange_type;
private String point_exchange;
private String max_use_point;
private String integral_give_type;
private String give_point;
private Object merchant;
private Integer commissionRate;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSketch() {
return sketch;
}

public void setSketch(String sketch) {
this.sketch = sketch;
}

public String getKeywords() {
return keywords;
}

public void setKeywords(String keywords) {
this.keywords = keywords;
}

public String getPicture() {
return picture;
}

public void setPicture(String picture) {
this.picture = picture;
}

public String getView() {
return view;
}

public void setView(String view) {
this.view = view;
}

public String getMatch_point() {
return match_point;
}

public void setMatch_point(String match_point) {
this.match_point = match_point;
}

public String getPrice() {
return price;
}

public void setPrice(String price) {
this.price = price;
}

public String getMarket_price() {
return market_price;
}

public void setMarket_price(String market_price) {
this.market_price = market_price;
}

public String getCost_price() {
return cost_price;
}

public void setCost_price(String cost_price) {
this.cost_price = cost_price;
}

public String getStock() {
return stock;
}

public void setStock(String stock) {
this.stock = stock;
}

public Integer getSales() {
return sales;
}

public void setSales(Integer sales) {
this.sales = sales;
}

public String getMerchant_id() {
return merchant_id;
}

public void setMerchant_id(String merchant_id) {
this.merchant_id = merchant_id;
}

public String getIs_open_presell() {
return is_open_presell;
}

public void setIs_open_presell(String is_open_presell) {
this.is_open_presell = is_open_presell;
}

public String getIs_open_commission() {
return is_open_commission;
}

public void setIs_open_commission(String is_open_commission) {
this.is_open_commission = is_open_commission;
}

public String getPoint_exchange_type() {
return point_exchange_type;
}

public void setPoint_exchange_type(String point_exchange_type) {
this.point_exchange_type = point_exchange_type;
}

public String getPoint_exchange() {
return point_exchange;
}

public void setPoint_exchange(String point_exchange) {
this.point_exchange = point_exchange;
}

public String getMax_use_point() {
return max_use_point;
}

public void setMax_use_point(String max_use_point) {
this.max_use_point = max_use_point;
}

public String getIntegral_give_type() {
return integral_give_type;
}

public void setIntegral_give_type(String integral_give_type) {
this.integral_give_type = integral_give_type;
}

public String getGive_point() {
return give_point;
}

public void setGive_point(String give_point) {
this.give_point = give_point;
}

public Object getMerchant() {
return merchant;
}

public void setMerchant(Object merchant) {
this.merchant = merchant;
}

public Integer getCommissionRate() {
return commissionRate;
}

public void setCommissionRate(Integer commissionRate) {
this.commissionRate = commissionRate;
}

}

+ 185
- 0
app/src/main/java/com/example/tidalairpeisong/user/bean/VersionInfo.java 查看文件

@@ -0,0 +1,185 @@
package com.example.tidalairpeisong.user.bean;

/**
* @ClassName VersionInfo
* @Antuor Administrator
* @Date 2021/10/11
* @Version 1.0
*/
public class VersionInfo {

private Integer code;
private String message;
private DataDTO data;
private Integer timestamp;

public Integer getCode() {
return code;
}

public void setCode(Integer code) {
this.code = code;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public DataDTO getData() {
return data;
}

public void setData(DataDTO data) {
this.data = data;
}

public Integer getTimestamp() {
return timestamp;
}

public void setTimestamp(Integer timestamp) {
this.timestamp = timestamp;
}

public static class DataDTO {
private String id;
private String merchant_id;
private String title;
private String version_id;
private String version;
private String package_size;
private String type;
private String content;
private String download_url;
private String is_enforce;
private String status;
private String download_num;
private String created_at;
private String updated_at;
private String cate_name;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getMerchant_id() {
return merchant_id;
}

public void setMerchant_id(String merchant_id) {
this.merchant_id = merchant_id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getVersion_id() {
return version_id;
}

public void setVersion_id(String version_id) {
this.version_id = version_id;
}

public String getVersion() {
return version;
}

public void setVersion(String version) {
this.version = version;
}

public String getPackage_size() {
return package_size;
}

public void setPackage_size(String package_size) {
this.package_size = package_size;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public String getDownload_url() {
return download_url;
}

public void setDownload_url(String download_url) {
this.download_url = download_url;
}

public String getIs_enforce() {
return is_enforce;
}

public void setIs_enforce(String is_enforce) {
this.is_enforce = is_enforce;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}

public String getDownload_num() {
return download_num;
}

public void setDownload_num(String download_num) {
this.download_num = download_num;
}

public String getCreated_at() {
return created_at;
}

public void setCreated_at(String created_at) {
this.created_at = created_at;
}

public String getUpdated_at() {
return updated_at;
}

public void setUpdated_at(String updated_at) {
this.updated_at = updated_at;
}

public String getCate_name() {
return cate_name;
}

public void setCate_name(String cate_name) {
this.cate_name = cate_name;
}
}
}

+ 48
- 0
app/src/main/java/com/example/tidalairpeisong/user/ui/activity/MainActivity.java 查看文件

@@ -0,0 +1,48 @@
package com.example.tidalairpeisong.user.ui.activity;

import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import com.example.tidalairpeisong.R;
import com.example.tidalairpeisong.rxhttp.error.OnError;
import com.example.tidalairpeisong.rxhttp.url.Api;
import com.example.tidalairpeisong.user.bean.MallProductBean;
import com.example.tidalairpeisong.user.bean.VersionInfo;
import com.rxjava.rxlife.RxLife;

import rxhttp.wrapper.param.RxHttp;


public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RxHttp.get(Api.version)
.add("type",1)
.add("version","2.2.2")
.asResponse(VersionInfo.class)
.to(RxLife.asOnMain(this))
.subscribe(s -> {
Log.e("csd",s.getData().getCate_name()+"");
}, (OnError) error -> {
Log.e("csd",error.getErrorMsg());

});

RxHttp.get(Api.mall_products)
.add("page",1)
.add("cate_id",1)
.asResponseList(MallProductBean.class)
.to(RxLife.asOnMain(this))
.subscribe(productBeans -> {
Log.e("csd",productBeans.size()+"");
},(OnError) error -> {
Log.e("csd",error.getErrorMsg());

});
}
}

+ 30
- 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml 查看文件

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

+ 170
- 0
app/src/main/res/drawable/ic_launcher_background.xml 查看文件

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

+ 18
- 0
app/src/main/res/layout/activity_main.xml 查看文件

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".user.ui.activity.MainActivity">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

+ 5
- 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml 查看文件

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

+ 5
- 0
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml 查看文件

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

二進制
app/src/main/res/mipmap-hdpi/ic_launcher.png 查看文件

Before After
Width: 72  |  Height: 72  |  Size: 3.5KB

二進制
app/src/main/res/mipmap-hdpi/ic_launcher_round.png 查看文件

Before After
Width: 72  |  Height: 72  |  Size: 5.2KB

二進制
app/src/main/res/mipmap-mdpi/ic_launcher.png 查看文件

Before After
Width: 48  |  Height: 48  |  Size: 2.6KB

二進制
app/src/main/res/mipmap-mdpi/ic_launcher_round.png 查看文件

Before After
Width: 48  |  Height: 48  |  Size: 3.3KB

二進制
app/src/main/res/mipmap-xhdpi/ic_launcher.png 查看文件

Before After
Width: 96  |  Height: 96  |  Size: 4.8KB

二進制
app/src/main/res/mipmap-xhdpi/ic_launcher_round.png 查看文件

Before After
Width: 96  |  Height: 96  |  Size: 7.3KB

二進制
app/src/main/res/mipmap-xxhdpi/ic_launcher.png 查看文件

Before After
Width: 144  |  Height: 144  |  Size: 7.7KB

二進制
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png 查看文件

Before After
Width: 144  |  Height: 144  |  Size: 12KB

二進制
app/src/main/res/mipmap-xxxhdpi/ic_launcher.png 查看文件

Before After
Width: 192  |  Height: 192  |  Size: 10KB

二進制
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png 查看文件

Before After
Width: 192  |  Height: 192  |  Size: 16KB

+ 16
- 0
app/src/main/res/values-night/themes.xml 查看文件

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.NewProject" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

+ 10
- 0
app/src/main/res/values/colors.xml 查看文件

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

+ 8
- 0
app/src/main/res/values/strings.xml 查看文件

@@ -0,0 +1,8 @@
<resources>
<string name="app_name">NewProject</string>

<string name="network_error">当前无网络,请检查你的网络设置</string>
<string name="notify_no_network">网络连接不可用,请稍候重试!</string>
<string name="esky_service_exception">网络不给力,请稍候再试!</string>
<string name="time_out_please_try_again_later">连接超时,请稍后重试</string>
</resources>

+ 16
- 0
app/src/main/res/values/themes.xml 查看文件

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.NewProject" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

+ 5
- 0
app/src/main/res/xml/network_security_config.xml 查看文件

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>

<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

+ 17
- 0
app/src/test/java/com/example/tidalairpeisong/ExampleUnitTest.java 查看文件

@@ -0,0 +1,17 @@
package com.example.tidalairpeisong;

import org.junit.Test;

import static org.junit.Assert.*;

/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

+ 26
- 0
build.gradle 查看文件

@@ -0,0 +1,26 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
maven { url "https://jitpack.io" }
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

+ 17
- 0
gradle.properties 查看文件

@@ -0,0 +1,17 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true

二進制
gradle/wrapper/gradle-wrapper.jar 查看文件


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties 查看文件

@@ -0,0 +1,6 @@
#Mon Oct 11 10:42:43 CST 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

+ 172
- 0
gradlew 查看文件

@@ -0,0 +1,172 @@
#!/usr/bin/env sh

##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
echo "$*"
}

die () {
echo
echo "$*"
echo
exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option

if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"

+ 84
- 0
gradlew.bat 查看文件

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega

+ 2
- 0
settings.gradle 查看文件

@@ -0,0 +1,2 @@
rootProject.name = "NewProject"
include ':app'

Loading…
取消
儲存