This commit is contained in:
2021-09-22 10:02:44 +08:00
commit f298a018c6
729 changed files with 56782 additions and 0 deletions

1
common/.gitignore vendored Normal file
View File

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

47
common/build.gradle Normal file
View File

@@ -0,0 +1,47 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion app_android.compileSdkVersion
buildToolsVersion app_android.buildToolsVersion
defaultConfig {
minSdkVersion app_android.minSdkVersion
targetSdkVersion app_android.targetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
api 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
//v1.5
api 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Because RxAndroid releases are few and far between, it is recommended you also
// explicitly depend on RxJava's latest version for bug fixes and new features.
// (see https://github.com/ReactiveX/RxJava/releases for latest 2.x.x version)
api 'io.reactivex.rxjava2:rxjava:2.2.12'
api 'androidx.preference:preference:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// 因为每一个 “子Module”都依赖了 common所有当我们在 common中依赖 arouter_api柱状
// 就等于 全部都依赖了 arouter_api
api project(":arouter_api")
}

View File

21
common/proguard-rules.pro vendored Normal file
View File

@@ -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

View File

@@ -0,0 +1,27 @@
package com.xiangxue.common.network;
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.xiangxue.common.network.test", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiangxue.common" />

View File

@@ -0,0 +1,66 @@
package com.xiangxue.common;
import com.xiangxue.common.bean.PathBean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 全局路径记录器(根据子模块分组)
*
* 5种方式通信 之一 全局map 已经废除了
*/
public class RecordPathManager {
// key:"order"组 value:order子模块下对应所有的Activity路径信息
private static Map<String, List<PathBean>> groupMap = new HashMap<>();
/**
* 将路径信息加入全局Map
*
* @param groupName 组名,如:"personal"
* @param pathName 路劲名,如:"Personal_MainActivity"
* @param clazz 类对象Personal_MainActivity.class
*/
public static void joinGroup(String groupName, String pathName, Class<?> clazz) {
List<PathBean> list = groupMap.get(groupName);
if (list == null) {
list = new ArrayList<>();
list.add(new PathBean(pathName, clazz));
groupMap.put(groupName, list);
} else {
groupMap.put(groupName, list);
}
groupMap.put(groupName, list);
}
/**
* 根据组名和路径名获取类对象,达到跳转目的
*
* @param groupName 组名
* @param pathName 路径名
* @return 跳转目标的class类对象
*/
public static Class<?> getTargetClass(String groupName, String pathName) {
List<PathBean> list = groupMap.get(groupName);
if (list == null) return null;
for (PathBean path : list) {
if (pathName.equalsIgnoreCase(path.getPath())) {
return path.getClazz();
}
}
return null;
}
/**
* 清理、回收
*/
public static void recycleGroup() {
groupMap.clear();
groupMap = null;
System.gc();
}
}

View File

@@ -0,0 +1,21 @@
package com.xiangxue.common.base;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.xiangxue.common.utils.Cons;
/**
* 项目父Activity
*/
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(Cons.TAG, "common/BaseActivity");
}
}

View File

@@ -0,0 +1,19 @@
package com.xiangxue.common.base;
import android.app.Application;
import android.util.Log;
import com.xiangxue.common.utils.Cons;
/**
* 项目父Application
*/
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Log.e(Cons.TAG, "common/BaseApplication");
}
}

View File

@@ -0,0 +1,37 @@
package com.xiangxue.common.bean;
/**
* 路径对象(公共基础库中,所有子模块都可以调用)
* 如:
* path : ”order/Order_MainActivity”
* clazz : Order_MainActivity.class
*/
public class PathBean {
private String path;
private Class clazz;
public PathBean() {
}
public PathBean(String path, Class clazz) {
this.path = path;
this.clazz = clazz;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Class getClazz() {
return clazz;
}
public void setClazz(Class clazz) {
this.clazz = clazz;
}
}

View File

@@ -0,0 +1,52 @@
package com.xiangxue.common.bean;
import java.io.Serializable;
public class Student implements Serializable {
private String name = "";
private String sex;
private int age;
/*public Student() {
}*/
public Student(String name, String sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}

View File

@@ -0,0 +1,10 @@
package com.xiangxue.common.images;
/**
* 图片加载管理器
*/
public class GlideManager {
// .....
}

View File

@@ -0,0 +1,45 @@
package com.xiangxue.common.network;
import com.xiangxue.common.network.base.NetworkApi;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
public class DoupanNetworkApi extends NetworkApi {
private static volatile DoupanNetworkApi sInstance;
public static DoupanNetworkApi getInstance() {
if (sInstance == null) {
synchronized (DoupanNetworkApi.class) {
if (sInstance == null) {
sInstance = new DoupanNetworkApi();
}
}
}
return sInstance;
}
@Override
protected Interceptor getInterceptor() {
return null;
}
@Override
protected <T> Function<T, T> getAppErrorHandler() {
return null;
}
public static <T> T getService(Class<T> service) {
return getInstance().getRetrofit(service).create(service);
}
@Override
public String getFormal() {
return "https://api.douban.com";
}
@Override
public String getTest() {
return "https://api.douban.com";
}
}

View File

@@ -0,0 +1,73 @@
package com.xiangxue.common.network;
import com.xiangxue.common.network.base.NetworkApi;
import com.xiangxue.common.network.beans.TecentBaseResponse;
import com.xiangxue.common.network.errorhandler.ExceptionHandle;
import com.xiangxue.common.network.utils.TecentUtil;
import java.io.IOException;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class TecentNetworkApi extends NetworkApi {
private static volatile TecentNetworkApi sInstance;
public static TecentNetworkApi getInstance() {
if (sInstance == null) {
synchronized (TecentNetworkApi.class) {
if (sInstance == null) {
sInstance = new TecentNetworkApi();
}
}
}
return sInstance;
}
public static <T> T getService(Class<T> service) {
return getInstance().getRetrofit(service).create(service);
}
@Override
protected Interceptor getInterceptor() {
return new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
String timeStr = TecentUtil.getTimeStr();
Request.Builder builder = chain.request().newBuilder();
// builder.addHeader("Source", "source");
// builder.addHeader("Authorization", TecentUtil.getAuthorization(timeStr));
// builder.addHeader("Date", timeStr);
return chain.proceed(builder.build());
}
};
}
protected <T> Function<T, T> getAppErrorHandler() {
return new Function<T, T>() {
@Override
public T apply(T response) throws Exception {
//response中code码不会0 出现错误
if (response instanceof TecentBaseResponse && ((TecentBaseResponse) response).success != 0) {
ExceptionHandle.ServerException exception = new ExceptionHandle.ServerException();
exception.code = ((TecentBaseResponse) response).success;
exception.message = ((TecentBaseResponse) response).msg != null ? ((TecentBaseResponse) response).msg : "";
throw exception;
}
return response;
}
};
}
@Override
public String getFormal() {
return "http://139.186.151.48/";
}
@Override
public String getTest() {
return "http://service-o5ikp40z-1255468759.ap-shanghai.apigateway.myqcloud.com/";
}
}

View File

@@ -0,0 +1,40 @@
package com.xiangxue.common.network.base;
import java.lang.reflect.Type;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import retrofit2.Call;
import retrofit2.CallAdapter;
public class CallAdapterFactory<R, W> implements CallAdapter<R, W> {
public static <R, W> CallAdapterFactory<R, W> create(@NonNull CallAdapter<R, W> mAdapter, @NonNull Function<W, W> mFunction) {
return new CallAdapterFactory(mAdapter, mFunction);
}
private CallAdapterFactory(@NonNull CallAdapter<R, W> mAdapter, @NonNull Function<W, W> mFunction) {
this.mAdapter = mAdapter;
this.mFunction = mFunction;
}
private CallAdapter<R, W> mAdapter;
private Function<W, W> mFunction;
@Override
public Type responseType() {
return mAdapter.responseType();
}
@Override
public W adapt(Call<R> call) {
W adapt = mAdapter.adapt(call);
try {
return mFunction.apply(adapt);
} catch (Exception e) {
e.printStackTrace();
}
return adapt;
}
}

View File

@@ -0,0 +1,14 @@
package com.xiangxue.common.network.base;
import android.app.Application;
/**
* Created by Allen on 2017/7/20.
* 保留所有版权,未经允许请不要分享到互联网和其他人
*/
public interface INetworkRequiredInfo {
String getAppVersionName();
String getAppVersionCode();
boolean isDebug();
Application getApplicationContext();
}

View File

@@ -0,0 +1,131 @@
package com.xiangxue.common.network.base;
import com.xiangxue.common.network.commoninterceptor.CommonRequestInterceptor;
import com.xiangxue.common.network.commoninterceptor.CommonResponseInterceptor;
import com.xiangxue.common.network.environment.EnvironmentActivity;
import com.xiangxue.common.network.environment.IEnvironment;
import java.util.HashMap;
import io.reactivex.functions.Function;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public abstract class NetworkApi implements IEnvironment {
private static INetworkRequiredInfo iNetworkRequiredInfo;
private static HashMap<String, Retrofit> retrofitHashMap = new HashMap<>();
private String mBaseUrl;
private OkHttpClient mOkHttpClient;
private static boolean mIsFormal = true;
public NetworkApi() {
if (!mIsFormal) {
mBaseUrl = getTest();
return;
}
mBaseUrl = getFormal();
}
public static void init(INetworkRequiredInfo networkRequiredInfo) {
iNetworkRequiredInfo = networkRequiredInfo;
mIsFormal = EnvironmentActivity.isOfficialEnvironment(networkRequiredInfo.getApplicationContext());
}
protected Retrofit getRetrofit(Class service) {
if (retrofitHashMap.get(mBaseUrl + service.getName()) != null) {
return retrofitHashMap.get(mBaseUrl + service.getName());
}
Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.baseUrl(mBaseUrl);
retrofitBuilder.client(getOkHttpClient());
retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
retrofitBuilder.addCallAdapterFactory(XiangxueRxJava2CallAdapterFactory.create(getAppErrorHandler()));
Retrofit retrofit = retrofitBuilder.build();
retrofitHashMap.put(mBaseUrl + service.getName(), retrofit);
return retrofit;
}
private OkHttpClient getOkHttpClient() {
if(mOkHttpClient == null) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
if (getInterceptor() != null) {
okHttpClientBuilder.addInterceptor(getInterceptor());
}
okHttpClientBuilder.addInterceptor(new CommonRequestInterceptor(iNetworkRequiredInfo));
okHttpClientBuilder.addInterceptor(new CommonResponseInterceptor());
if (iNetworkRequiredInfo != null &&(iNetworkRequiredInfo.isDebug())) {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(httpLoggingInterceptor);
}
mOkHttpClient = okHttpClientBuilder.build();
}
return mOkHttpClient;
}
public static OkHttpClient getOkHttpClientt() {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addInterceptor(new CommonRequestInterceptor(iNetworkRequiredInfo));
okHttpClientBuilder.addInterceptor(new CommonResponseInterceptor());
if (iNetworkRequiredInfo != null &&(iNetworkRequiredInfo.isDebug())) {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(httpLoggingInterceptor);
}else {
}
return okHttpClientBuilder.build();
}
// public static void getTencentNewsChannels(){
// Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
// retrofitBuilder.baseUrl("http://139.186.151.48/");
// retrofitBuilder.client(getOkHttpClientt());
// retrofitBuilder.addConverterFactory(GsonConverterFactory.create());
// retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
// Retrofit retrofit = retrofitBuilder.build();
// NewsApiInterface newsApiInterface = retrofit.create(NewsApiInterface.class);
// newsApiInterface.getNowVersion()
// .subscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(new Observer<GetVesionResponseBean>() {
// @Override
// public void onSubscribe(@NonNull Disposable d) {
//
// }
//
// @Override
// public void onNext(@NonNull GetVesionResponseBean getVesionResponseBean) {
// Log.e("TIAOSHI", new Gson().toJson(getVesionResponseBean));
// }
//
// @Override
// public void onError(@NonNull Throwable e) {
//
// }
//
// @Override
// public void onComplete() {
//
// }
// });
//
//// nowVersion.enqueue(new Callback<GetVesionResponseBean>() {
//// @Override
//// public void onResponse(Call<GetVesionResponseBean> call, Response<GetVesionResponseBean> response) {
//// Log.e("TIAOSHI", new Gson().toJson(response.body()));
//// }
////
//// @Override
//// public void onFailure(Call<GetVesionResponseBean> call, Throwable t) {
//// Log.e("TIAOSHI", t.getMessage());
//// }
//// });
// }
protected abstract Interceptor getInterceptor();
protected abstract <T> Function<T, T> getAppErrorHandler();
}

View File

@@ -0,0 +1,68 @@
package com.xiangxue.common.network.base;
import com.xiangxue.common.network.errorhandler.HttpErrorHandler;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import retrofit2.CallAdapter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
public class XiangxueRxJava2CallAdapterFactory extends CallAdapter.Factory {
Function function;
private CallAdapter.Factory mFactory;
public static XiangxueRxJava2CallAdapterFactory create(Function function) {
return new XiangxueRxJava2CallAdapterFactory(function);
}
private XiangxueRxJava2CallAdapterFactory(Function function) {
this.function = function;
mFactory = RxJava2CallAdapterFactory.create();
}
@Override
public CallAdapter<?, ?> get(@NonNull Type returnType, @NonNull Annotation[] annotations, @NonNull Retrofit retrofit) {
final CallAdapter<?, ?> callAdapter = mFactory.get(returnType, annotations, retrofit);
Class<?> rawType = getRawType(returnType);
if(callAdapter != null) {
//生产不同的CallAdapter
if (rawType == Observable.class) {
return CallAdapterFactory.create((CallAdapter<Observable<?>, Observable<?>>) callAdapter, new Function<Observable<?>, Observable<?>>() {
@Override
public Observable<?> apply(@NonNull Observable<?> f) throws Exception {
Observable<?> observable = f.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
if (function != null) {
return observable.map(function).onErrorResumeNext(new HttpErrorHandler());
} else {
return observable.onErrorResumeNext(new HttpErrorHandler());
}
}
});
}
if (rawType == Flowable.class) {
return CallAdapterFactory.create((CallAdapter<Flowable<?>, Flowable<?>>) callAdapter, new Function<Flowable<?>, Flowable<?>>() {
@Override
public Flowable<?> apply(@NonNull Flowable<?> f) throws Exception {
Flowable<?> observable = f.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
if (function != null) {
return observable.map(function).onErrorResumeNext(new HttpErrorHandler());
} else {
return observable.onErrorResumeNext(new HttpErrorHandler());
}
}
});
}
}
//省略...
return callAdapter;
}
}

View File

@@ -0,0 +1,17 @@
package com.xiangxue.common.network.beans;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Created by Allen on 2017/7/20.
* 保留所有版权,未经允许请不要分享到互联网和其他人
*/
public class TecentBaseResponse {
@SerializedName("success")
@Expose
public Integer success;
@SerializedName("msg")
@Expose
public String msg;
}

View File

@@ -0,0 +1,23 @@
package com.xiangxue.common.network.commoninterceptor;
import com.xiangxue.common.network.base.INetworkRequiredInfo;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class CommonRequestInterceptor implements Interceptor {
private INetworkRequiredInfo requiredInfo;
public CommonRequestInterceptor(INetworkRequiredInfo requiredInfo){
this.requiredInfo = requiredInfo;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("os", "android");
builder.addHeader("appVersion",this.requiredInfo.getAppVersionCode());
return chain.proceed(builder.build());
}
}

View File

@@ -0,0 +1,19 @@
package com.xiangxue.common.network.commoninterceptor;
import android.util.Log;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Response;
public class CommonResponseInterceptor implements Interceptor {
private static final String TAG = "ResponseInterceptor";
@Override
public Response intercept(Chain chain) throws IOException {
long requestTime = System.currentTimeMillis();
Response response = chain.proceed(chain.request());
Log.d(TAG, "requestTime="+ (System.currentTimeMillis() - requestTime));
return response;
}
}

View File

@@ -0,0 +1,65 @@
package com.xiangxue.common.network.environment;
import android.app.Application;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import com.xiangxue.common.R;
public class EnvironmentActivity extends AppCompatActivity {
public static final String NETWORK_ENVIRONMENT_PREF_KEY = "network_environment_type";
private static String sCurrentNetworkEnvironment = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_environment);
//setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
getSupportFragmentManager().beginTransaction()
.replace(R.id.content, new MyPreferenceFragment())
.commit();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
sCurrentNetworkEnvironment = prefs.getString(EnvironmentActivity.NETWORK_ENVIRONMENT_PREF_KEY, "1");
}
public static class MyPreferenceFragment extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener {
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.environment_preference);
findPreference(NETWORK_ENVIRONMENT_PREF_KEY).setOnPreferenceChangeListener(this);
}
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
if (!sCurrentNetworkEnvironment.equalsIgnoreCase(String.valueOf(o))) {
Toast.makeText(getContext(), "您已经更改了网络环境再您退出当前页面的时候APP将会重启切换环境", Toast.LENGTH_SHORT).show();
}
return true;
}
}
@Override
public void onBackPressed() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String newValue = prefs.getString(EnvironmentActivity.NETWORK_ENVIRONMENT_PREF_KEY, "1");
if (!sCurrentNetworkEnvironment.equalsIgnoreCase(newValue)) {
android.os.Process.killProcess(android.os.Process.myPid());
} else {
finish();
}
}
public static boolean isOfficialEnvironment(Application application) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application);
String environment = prefs.getString(EnvironmentActivity.NETWORK_ENVIRONMENT_PREF_KEY, "1");
return "1".equalsIgnoreCase(environment);
}
}

View File

@@ -0,0 +1,7 @@
package com.xiangxue.common.network.environment;
public interface IEnvironment {
String getFormal();
String getTest();
}

View File

@@ -0,0 +1,136 @@
package com.xiangxue.common.network.errorhandler;
import android.net.ParseException;
import com.google.gson.JsonParseException;
import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONException;
import java.net.ConnectException;
import retrofit2.HttpException;
/**
* Created by Allen on 2017/7/20.
* 保留所有版权,未经允许请不要分享到互联网和其他人
*/
public class ExceptionHandle {
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 ResponeThrowable handleException(Throwable e) {
ResponeThrowable ex;
if (e instanceof HttpException) {
HttpException httpException = (HttpException) e;
ex = new ResponeThrowable(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 ResponeThrowable(resultException, resultException.code);
ex.message = resultException.message;
return ex;
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
ex = new ResponeThrowable(e, ERROR.PARSE_ERROR);
ex.message = "解析错误";
return ex;
} else if (e instanceof ConnectException) {
ex = new ResponeThrowable(e, ERROR.NETWORD_ERROR);
ex.message = "连接失败";
return ex;
} else if (e instanceof javax.net.ssl.SSLHandshakeException) {
ex = new ResponeThrowable(e, ERROR.SSL_ERROR);
ex.message = "证书验证失败";
return ex;
} else if (e instanceof ConnectTimeoutException){
ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
ex.message = "连接超时";
return ex;
} else if (e instanceof java.net.SocketTimeoutException) {
ex = new ResponeThrowable(e, ERROR.TIMEOUT_ERROR);
ex.message = "连接超时";
return ex;
}
else {
ex = new ResponeThrowable(e, ERROR.UNKNOWN);
ex.message = "未知错误";
return ex;
}
}
/**
* 约定异常
*/
public class ERROR {
/**
* 未知错误
*/
public static final int UNKNOWN = 1000;
/**
* 解析错误
*/
public static final int PARSE_ERROR = 1001;
/**
* 网络错误
*/
public static final int NETWORD_ERROR = 1002;
/**
* 协议出错
*/
public static final int HTTP_ERROR = 1003;
/**
* 证书出错
*/
public static final int SSL_ERROR = 1005;
/**
* 连接超时
*/
public static final int TIMEOUT_ERROR = 1006;
}
public static class ResponeThrowable extends Exception {
public int code;
public String message;
public ResponeThrowable(Throwable throwable, int code) {
super(throwable);
this.code = code;
}
@Override
public String getMessage(){
return message;
}
}
public static class ServerException extends RuntimeException {
public int code;
public String message;
}
}

View File

@@ -0,0 +1,21 @@
package com.xiangxue.common.network.errorhandler;
import io.reactivex.Observable;
import io.reactivex.functions.Function;
/**
* Created by Allen on 2017/7/20.
* 保留所有版权,未经允许请不要分享到互联网和其他人
*/
/**
* HttpResponseFunc处理以下两类网络错误
* 1、http请求相关的错误例如404403socket timeout等等
* 2、应用数据的错误会抛RuntimeException最后也会走到这个函数来统一处理
*/
public class HttpErrorHandler<T> implements Function<Throwable, Observable<T>> {
@Override
public io.reactivex.Observable<T> apply(Throwable throwable) throws Exception {
return io.reactivex.Observable.error(ExceptionHandle.handleException(throwable));
}
}

View File

@@ -0,0 +1,29 @@
package com.xiangxue.common.network.observer;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
public abstract class BaseObserver<T> implements Observer<T> {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(T t) {
onSuccess(t);
}
@Override
public void onError(Throwable e) {
onFailure(e);
}
@Override
public void onComplete() {
}
public abstract void onSuccess(T t);
public abstract void onFailure(Throwable e);
}

View File

@@ -0,0 +1,99 @@
package com.xiangxue.common.network.utils;
import java.io.UnsupportedEncodingException;
public class Base64 {
private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/' };
private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
-1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
-1, -1 };
public static String encode(byte[] data) {
StringBuffer sb = new StringBuffer();
int len = data.length;
int i = 0;
int b1, b2, b3;
while (i < len) {
b1 = data[i++] & 0xff;
if (i == len) {
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
sb.append("==");
break;
}
b2 = data[i++] & 0xff;
if (i == len) {
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
sb.append("=");
break;
}
b3 = data[i++] & 0xff;
sb.append(base64EncodeChars[b1 >>> 2]);
sb.append(base64EncodeChars[((b1 & 0x03) << 4)
| ((b2 & 0xf0) >>> 4)]);
sb.append(base64EncodeChars[((b2 & 0x0f) << 2)
| ((b3 & 0xc0) >>> 6)]);
sb.append(base64EncodeChars[b3 & 0x3f]);
}
return sb.toString();
}
public static byte[] decode(String str) throws UnsupportedEncodingException {
StringBuffer sb = new StringBuffer();
byte[] data = str.getBytes("US-ASCII");
int len = data.length;
int i = 0;
int b1, b2, b3, b4;
while (i < len) {
/* b1 */
do {
b1 = base64DecodeChars[data[i++]];
} while (i < len && b1 == -1);
if (b1 == -1)
break;
/* b2 */
do {
b2 = base64DecodeChars[data[i++]];
} while (i < len && b2 == -1);
if (b2 == -1)
break;
sb.append((char) ((b1 << 2) | ((b2 & 0x30) >>> 4)));
/* b3 */
do {
b3 = data[i++];
if (b3 == 61)
return sb.toString().getBytes("ISO-8859-1");
b3 = base64DecodeChars[b3];
} while (i < len && b3 == -1);
if (b3 == -1)
break;
sb.append((char) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));
/* b4 */
do {
b4 = data[i++];
if (b4 == 61)
return sb.toString().getBytes("ISO-8859-1");
b4 = base64DecodeChars[b4];
} while (i < len && b4 == -1);
if (b4 == -1)
break;
sb.append((char) (((b3 & 0x03) << 6) | b4));
}
return sb.toString().getBytes("ISO-8859-1");
}
}

View File

@@ -0,0 +1,57 @@
package com.xiangxue.common.network.utils;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public final class TecentUtil {
public static final String secretId = "AKIDbdB15u6x60cw50p242zez6lj3v8vhjtbbg8";
public static final String secretKey = "4g7w4RqetblslngIxoUqkhtyf2pdy15dAml8uu9e";
private static final String CONTENT_CHARSET = "UTF-8";
private static final String HMAC_ALGORITHM = "HmacSHA1";
private TecentUtil(){
}
private static String sign(String secret, String timeStr) {
//get signStr
String signStr = "date: " + timeStr + "\n" + "source: " + "source";
//get sig
try {
Mac mac1 = Mac.getInstance(HMAC_ALGORITHM);
byte[] hash;
SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(CONTENT_CHARSET), mac1.getAlgorithm());
mac1.init(secretKey);
hash = mac1.doFinal(signStr.getBytes(CONTENT_CHARSET));
String sig = new String(Base64.encode(hash));
System.out.println("signValue--->" + sig);
return sig;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static String getAuthorization(String timeStr){
String sig = sign(secretKey, timeStr);
return "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"date source\", signature=\"" + sig + "\"";
}
public static String getTimeStr(){
Calendar cd = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
return sdf.format(cd.getTime());
}
}

View File

@@ -0,0 +1,9 @@
package com.xiangxue.common.order;
import com.xiangxue.arouter_api.Call;
public interface OrderDrawable extends Call {
int getDrawable();
}

View File

@@ -0,0 +1,13 @@
package com.xiangxue.common.order.net;
import com.xiangxue.arouter_api.Call;
import java.io.IOException;
/**
* 订单模块对外暴露接口,其他模块可以获取返回业务数据
*/
public interface OrderAddress extends Call {
OrderBean getOrderBean(String key, String ip) throws IOException;
}

View File

@@ -0,0 +1,105 @@
package com.xiangxue.common.order.net;
/**
* {"resultcode":"200","reason":"查询成功",
* "result":{"Country":"美国","Province":"加利福尼亚","City":"","Isp":""},"error_code":0}
*/
public class OrderBean {
private String resultcode;
private String reason;
private Result result;
private int error_code;
public static class Result {
private String Country;
private String Province;
private String City;
private String Isp;
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
public String getProvince() {
return Province;
}
public void setProvince(String province) {
Province = province;
}
public String getCity() {
return City;
}
public void setCity(String city) {
City = city;
}
public String getIsp() {
return Isp;
}
public void setIsp(String isp) {
Isp = isp;
}
@Override
public String toString() {
return "Result{" +
"Country='" + Country + '\'' +
", Province='" + Province + '\'' +
", City='" + City + '\'' +
", Isp='" + Isp + '\'' +
'}';
}
}
public String getResultcode() {
return resultcode;
}
public void setResultcode(String resultcode) {
this.resultcode = resultcode;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
@Override
public String toString() {
return "OrderBean{" +
"resultcode='" + resultcode + '\'' +
", reason='" + reason + '\'' +
", result=" + result +
", error_code=" + error_code +
'}';
}
}

View File

@@ -0,0 +1,66 @@
package com.xiangxue.common.order.user;
import java.io.Serializable;
/**
* 例如:用户实体父类
*/
public class BaseUser implements Serializable {
private String name;
private String account;
private String password;
private String phoneNumber;
private int gender;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
@Override
public String toString() {
return "BaseUser{" +
"name='" + name + '\'' +
", account='" + account + '\'' +
", password='" + password + '\'' +
", phoneNumber='" + phoneNumber + '\'' +
", gender=" + gender +
'}';
}
}

View File

@@ -0,0 +1,12 @@
package com.xiangxue.common.order.user;
import com.xiangxue.arouter_api.Call;
public interface IUser extends Call {
/**
* @return 根据不同子模块的具体实现,调用得到不同的结果
*/
BaseUser getUserInfo();
}

View File

@@ -0,0 +1,7 @@
package com.xiangxue.common.utils;
/**
* 常用工具类
*/
public final class CommonUtils {
}

View File

@@ -0,0 +1,7 @@
package com.xiangxue.common.utils;
public final class Cons {
public static final String TAG = "Derray";
}

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="56dp"
android:height="56dp"
android:viewportWidth="56"
android:viewportHeight="56">
<path
android:fillColor="#FF000000"
android:pathData="M8,41.08V2c0,-0.553 -0.448,-1 -1,-1S6,1.447 6,2v39.08C2.613,41.568 0,44.481 0,48c0,3.859 3.14,7 7,7s7,-3.141 7,-7C14,44.481 11.387,41.568 8,41.08zM7,53c-2.757,0 -5,-2.243 -5,-5s2.243,-5 5,-5s5,2.243 5,5S9.757,53 7,53z"/>
<path
android:fillColor="#FF000000"
android:pathData="M29,20.695V2c0,-0.553 -0.448,-1 -1,-1s-1,0.447 -1,1v18.632c-3.602,0.396 -6.414,3.456 -6.414,7.161s2.812,6.765 6.414,7.161V54c0,0.553 0.448,1 1,1s1,-0.447 1,-1V34.891c3.4,-0.577 6,-3.536 6,-7.098S32.4,21.272 29,20.695zM27.793,33c-2.871,0 -5.207,-2.336 -5.207,-5.207s2.335,-5.207 5.207,-5.207S33,24.922 33,27.793S30.664,33 27.793,33z"/>
<path
android:fillColor="#FF000000"
android:pathData="M56,8c0,-3.859 -3.14,-7 -7,-7s-7,3.141 -7,7c0,3.519 2.613,6.432 6,6.92V54c0,0.553 0.448,1 1,1s1,-0.447 1,-1V14.92C53.387,14.432 56,11.519 56,8zM49,13c-2.757,0 -5,-2.243 -5,-5s2.243,-5 5,-5s5,2.243 5,5S51.757,13 49,13z"/>
</vector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<layout>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</layout>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="environmentArray">
<item>正式</item>
<item>测试</item>
</string-array>
<string-array name="environmentValues">
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@@ -0,0 +1,4 @@
<resources>
<string name="app_name">network</string>
<string name="network_environment_setting">开发者设置</string>
</resources>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue="1"
android:entries="@array/environmentArray"
android:entryValues="@array/environmentValues"
android:icon="@drawable/ic_controls"
android:key="network_environment_type"
android:summary="请您选择您需要使用的网络环境选择完后会重启APP生效"
android:title="设置网络环境" />
</PreferenceScreen>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

View File

@@ -0,0 +1,17 @@
package com.xiangxue.common.network;
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);
}
}