全志Launcher代码首次提交
This commit is contained in:
30
mylibrary/src/main/java/com/android/api/ServerApi.java
Normal file
30
mylibrary/src/main/java/com/android/api/ServerApi.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.android.api;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.HeaderMap;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.QueryMap;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/6/9 0009.
|
||||
*/
|
||||
|
||||
public interface ServerApi {
|
||||
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
@POST(ServerInterface.POST_EVENTINFO_DEVICE)
|
||||
Call<String> recoedDeviceEvent(@HeaderMap Map<String,String> headeMap, @Body RequestBody requestBody);
|
||||
|
||||
//获取广告接口
|
||||
@Headers({"Content-type:application/json;charset=UTF-8"})
|
||||
@POST(ServerInterface.POST_LAUNCHER_ADS)
|
||||
Call<String> postLauncherAds(@Body RequestBody requestBody);
|
||||
|
||||
}
|
||||
39
mylibrary/src/main/java/com/android/api/ServerInterface.java
Normal file
39
mylibrary/src/main/java/com/android/api/ServerInterface.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.android.api;
|
||||
|
||||
|
||||
import com.android.api.encrytion.UtilEncrypt;
|
||||
import com.android.util.DeviceUtil;
|
||||
import com.android.util.LogUtils;
|
||||
|
||||
public class ServerInterface {
|
||||
|
||||
public static final int SUCCESS = 200;
|
||||
public static final String IP_ADDRESS="192.168.1.87";
|
||||
|
||||
/**心跳业务IP*/
|
||||
public static final String SERVER_IP_ADDRESS="181b9296940b2b9787a4b781ce52c18f65cb2ae18cfbeb7fa4b6e99dded7f945";
|
||||
/**其他业务IP*/
|
||||
public static final String BUSINESS_IP_ADDRESS="e50cce9d2db6d36b3d13f60ef00e9c1a609e3f82a2fa708bb93b459b2939713c";
|
||||
|
||||
//获取launcher广告资源信息
|
||||
public static final String POST_LAUNCHER_ADS="/app-api/launcher/getLauncher/ads";
|
||||
|
||||
/**上传事件信息*/
|
||||
public static final String POST_EVENTINFO_DEVICE="/app-api/third/launcher/ad/play/callback";
|
||||
|
||||
private static final boolean USER_DEBUG=false;
|
||||
|
||||
|
||||
public static String createHttpUrl(){
|
||||
if(USER_DEBUG) {
|
||||
LogUtils.loge("TEST MODEL");
|
||||
return "http://" + IP_ADDRESS + ":8748";
|
||||
}else {
|
||||
LogUtils.loge("RUNING MODEL");
|
||||
return "http://"+UtilEncrypt.decrypt(BUSINESS_IP_ADDRESS)+":8748";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
87
mylibrary/src/main/java/com/android/api/biz/BaseBiz.java
Normal file
87
mylibrary/src/main/java/com/android/api/biz/BaseBiz.java
Normal file
@@ -0,0 +1,87 @@
|
||||
package com.android.api.biz;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
||||
import com.android.api.ServerInterface;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.Cookie;
|
||||
import okhttp3.CookieJar;
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.scalars.ScalarsConverterFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2017/11/11 0011.
|
||||
* 网络请求基类
|
||||
*/
|
||||
|
||||
public class BaseBiz {
|
||||
private Retrofit stringRetrofit;//返回字符串
|
||||
private static final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();
|
||||
|
||||
public BaseBiz() {
|
||||
// stringRetrofit = new Retrofit.Builder().baseUrl(ServerInterface.BASE_URL)
|
||||
// .addConverterFactory(ScalarsConverterFactory.create())
|
||||
// .client(getClient())
|
||||
// .build();
|
||||
}
|
||||
|
||||
public BaseBiz(String baseUrl) {
|
||||
stringRetrofit = new Retrofit.Builder().baseUrl(baseUrl)
|
||||
.addConverterFactory(ScalarsConverterFactory.create())
|
||||
.client(getClient())
|
||||
.build();
|
||||
}
|
||||
|
||||
protected Retrofit getStringRetrofit() {
|
||||
return stringRetrofit;
|
||||
}
|
||||
|
||||
public static OkHttpClient getClient() {
|
||||
return new OkHttpClient.Builder()
|
||||
.connectTimeout(30000, TimeUnit.MILLISECONDS)
|
||||
.addInterceptor(new Interceptor() {
|
||||
Request request;
|
||||
|
||||
@Override
|
||||
public Response intercept(@NonNull Chain chain) throws IOException {
|
||||
// if (MyApplication.getUserBean() != null) {
|
||||
// request = chain.request().newBuilder()
|
||||
//// .addHeader("token", MyApplication.getUserBean().getToken())
|
||||
// .build();
|
||||
// } else {
|
||||
request = chain.request().newBuilder().addHeader("d-time", String.valueOf(System.currentTimeMillis())).build();
|
||||
// }
|
||||
if (request.body() == null) {
|
||||
} else {
|
||||
}
|
||||
return chain.proceed(request);
|
||||
}
|
||||
}).cookieJar(new CookieJar() {
|
||||
@Override
|
||||
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
||||
cookieStore.put(CoreKeys.SESSIONID, cookies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Cookie> loadForRequest(HttpUrl url) {
|
||||
List<Cookie> cookies = cookieStore.get(CoreKeys.SESSIONID);
|
||||
return cookies != null ? cookies : new ArrayList<Cookie>();
|
||||
}
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
27
mylibrary/src/main/java/com/android/api/biz/Biz.java
Normal file
27
mylibrary/src/main/java/com/android/api/biz/Biz.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.android.api.biz;
|
||||
|
||||
|
||||
import com.android.api.biz.OnBaseListener;
|
||||
import com.android.database.lib.RecordEventBean;
|
||||
import com.android.nebulasdk.bean.EventDataInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/6/9 0009.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public interface Biz {
|
||||
|
||||
|
||||
//获取广告接口
|
||||
void postLauncherAds(Map<String ,String > map, OnBaseListener listener);
|
||||
//记录设备事件的接口
|
||||
void postEventData(List<EventDataInfo> recordEventBeans, OnBaseListener listener);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
17
mylibrary/src/main/java/com/android/api/biz/CoreKeys.java
Normal file
17
mylibrary/src/main/java/com/android/api/biz/CoreKeys.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.android.api.biz;
|
||||
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class CoreKeys {
|
||||
|
||||
public static final String SESSIONID = "sessionid";
|
||||
public static final String CONFIGDATABEAN="ConfigDataBean";
|
||||
|
||||
public static String local_file = Environment.getExternalStorageDirectory()
|
||||
+ File.separator + Environment.DIRECTORY_DCIM
|
||||
+ File.separator + "Camera" + File.separator;
|
||||
public static String down_file = Environment.getExternalStorageDirectory().getAbsolutePath() + "/atv-ota/";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.android.api.biz;
|
||||
|
||||
|
||||
public interface OnBaseListener {
|
||||
|
||||
/**
|
||||
* 服务器响应
|
||||
*/
|
||||
void onResponse(String result);
|
||||
|
||||
/**
|
||||
* 服务器未响应
|
||||
*/
|
||||
void onFailure(String e, int code);
|
||||
}
|
||||
114
mylibrary/src/main/java/com/android/api/biz/bizimpl/BizImpl.java
Normal file
114
mylibrary/src/main/java/com/android/api/biz/bizimpl/BizImpl.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package com.android.api.biz.bizimpl;
|
||||
|
||||
import com.android.api.biz.Biz;
|
||||
import com.android.nebulasdk.bean.EventDataInfo;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.android.api.ServerApi;
|
||||
import com.android.api.biz.BaseBiz;
|
||||
import com.android.api.biz.OnBaseListener;
|
||||
import com.android.database.lib.RecordEventBean;
|
||||
import com.android.util.GsonUtil;
|
||||
import com.android.util.LogUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.RequestBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/6/9 0009.
|
||||
*/
|
||||
|
||||
public class BizImpl extends BaseBiz implements Biz {
|
||||
|
||||
public BizImpl(String httpUrl) {
|
||||
super(httpUrl);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void postLauncherAds(Map<String, String> map, OnBaseListener listener) {
|
||||
{
|
||||
JsonObject jsonObject =new JsonObject();
|
||||
Iterator<String> it = map.keySet().iterator();
|
||||
while (it.hasNext()){
|
||||
String keyStr= it.next();
|
||||
String valueStr= (String)map.get(keyStr);
|
||||
jsonObject.addProperty(keyStr,valueStr);
|
||||
}
|
||||
RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),GsonUtil.GsonString(jsonObject));
|
||||
getStringRetrofit().create(ServerApi.class).postLauncherAds(requestBody).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (call != null) {
|
||||
if (response.body() != null) {
|
||||
LogUtils.loge("postLauncherAds response==>" + GsonUtil.GsonString(response.body()));
|
||||
if (response.isSuccessful()) {
|
||||
listener.onResponse(response.body());
|
||||
} else {
|
||||
listener.onFailure(response.message(), response.raw().code());
|
||||
}
|
||||
} else {
|
||||
listener.onFailure("The server is busy, please try again later", response.raw().code());
|
||||
}
|
||||
} else {
|
||||
LogUtils.loge(">>>>>>>>>>>>>>>>>>call == null<<<<<<<<<<<<<<<<<<");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
if (call.isExecuted()) {
|
||||
call.cancel();
|
||||
}
|
||||
LogUtils.loge("postLauncherAds request fail==>" + GsonUtil.GsonString(t.getMessage()));
|
||||
listener.onFailure("The server is busy, please try again later", 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void postEventData(List<EventDataInfo> recordEventBeans, OnBaseListener listener) {
|
||||
Map<String,String> heardMap = new HashMap<>();
|
||||
RequestBody requestBody = RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), GsonUtil.GsonString(recordEventBeans));
|
||||
getStringRetrofit().create(ServerApi.class).recoedDeviceEvent(heardMap,requestBody).enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(Call<String> call, Response<String> response) {
|
||||
if (call != null) {
|
||||
if (response.body() != null) {
|
||||
// LogUtils.loge("submit record events" + GsonUtil.GsonString(response.body()));
|
||||
// String test="{\\\"code\\\": \\\"1000\\\",\\\"msg\\\": \\\"获取成功\\\",\\\"data\\\": [\\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"胡治银\\\",\\\"punchTime\\\": \\\"2018-12-12 8:30:00\\\",\\\"punchResult\\\": 迟到}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"杨荣香\\\",\\\"punchTime\\\": \\\"2018-12-12 7:30:00\\\",\\\"punchResult\\\": 正常}\\\", \\\"{\\\"picUrl\\\": \\\"www.baidu.com\\\",\\\"peopleName\\\": \\\"张三\\\",\\\"punchTime\\\": \\\"2018-12-12 15:03:01\\\",\\\"punchResult\\\": 迟到}\\\"]\n" +
|
||||
// "}";
|
||||
if (response.isSuccessful()) {
|
||||
listener.onResponse(response.body());
|
||||
} else {
|
||||
listener.onFailure(response.message(), response.raw().code());
|
||||
}
|
||||
} else {
|
||||
listener.onFailure("The server is busy, please try again later", response.raw().code());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<String> call, Throwable t) {
|
||||
if (call.isExecuted()) {
|
||||
call.cancel();
|
||||
}
|
||||
LogUtils.loge("recoedDeviceEvent Biz服务器未响应请求失败==>" + GsonUtil.GsonString(t.getMessage()));
|
||||
listener.onFailure("The server is busy, please try again later", 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.android.api.encrytion;
|
||||
|
||||
|
||||
|
||||
public class AESUtil {
|
||||
|
||||
|
||||
private static final String password="wwwwaaabbb";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dataStr
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public static String encryptVerification(String dataStr){
|
||||
|
||||
if(dataStr==null||"".equals(dataStr)){
|
||||
return "";
|
||||
}
|
||||
String headMsg="";
|
||||
String endMag="";
|
||||
String addendMag="";
|
||||
if(dataStr.length()>3) {
|
||||
headMsg = dataStr.substring(0,3);
|
||||
}
|
||||
if(dataStr.length()>4){
|
||||
endMag=dataStr.substring(dataStr.length()-4,dataStr.length());
|
||||
}
|
||||
if(dataStr.length()>7){
|
||||
addendMag=dataStr.substring(0,7);
|
||||
}
|
||||
String time=TimeUtil.getDateEND(System.currentTimeMillis());
|
||||
String tmp=headMsg+time+addendMag+endMag;
|
||||
String verification = MD5Utils.md5(tmp).substring(0,15);
|
||||
return UtilEncrypt.encrypt(password,verification);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// /**
|
||||
// * 测试
|
||||
// *
|
||||
// * @param args
|
||||
// * @throws Exception
|
||||
// */
|
||||
// public static void main(String[] args) throws Exception {
|
||||
//// String test= encryptVerification("8618665362153","123456");
|
||||
//
|
||||
// String test=UtilEncrypt.encrypt("test","123456");
|
||||
// System.out.print(test);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.android.api.encrytion;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
* Created by jzm on 2016/7/18.
|
||||
*/
|
||||
public class MD5Utils {
|
||||
|
||||
/**
|
||||
* 使用md5的算法进行加密
|
||||
*/
|
||||
public static String md5(String encryptStr) {
|
||||
MessageDigest md5;
|
||||
try {
|
||||
md5 = MessageDigest.getInstance("MD5");
|
||||
byte[] md5Bytes = md5.digest(encryptStr.getBytes());
|
||||
StringBuffer hexValue = new StringBuffer();
|
||||
for (int i = 0; i < md5Bytes.length; i++) {
|
||||
int val = ((int) md5Bytes[i]) & 0xff;
|
||||
if (val < 16)
|
||||
hexValue.append("0");
|
||||
hexValue.append(Integer.toHexString(val));
|
||||
}
|
||||
encryptStr = hexValue.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return encryptStr.toLowerCase();
|
||||
}
|
||||
}
|
||||
527
mylibrary/src/main/java/com/android/api/encrytion/TimeUtil.java
Normal file
527
mylibrary/src/main/java/com/android/api/encrytion/TimeUtil.java
Normal file
@@ -0,0 +1,527 @@
|
||||
package com.android.api.encrytion;
|
||||
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
|
||||
/**
|
||||
* 时间转换工具
|
||||
*/
|
||||
public class TimeUtil {
|
||||
public static final long DAY_MILLSECONDS = 24 * 3600 * 1000;
|
||||
|
||||
private TimeUtil() {
|
||||
}
|
||||
|
||||
public static String showMessageTime(long MessageTime) {
|
||||
SimpleDateFormat format;
|
||||
String showtimeString;
|
||||
long startTime = MessageTime * 1000;
|
||||
//获取当前年份
|
||||
int current_year = Integer.parseInt(getYear(System.currentTimeMillis()));
|
||||
//获取发消息的年份
|
||||
int year = Integer.parseInt(getYear(startTime));
|
||||
if (current_year > year) {
|
||||
//不在同一年 显示完整的年月日
|
||||
showtimeString = getDateEN(startTime);
|
||||
} else {
|
||||
if (newchajitian(startTime) == 0) {
|
||||
//同一天 显示时分
|
||||
format = new SimpleDateFormat("HH:mm");
|
||||
showtimeString = format.format(new Date(startTime));
|
||||
} else if (newchajitian(startTime) == 1) {
|
||||
//相差一天 显示昨天
|
||||
showtimeString = "昨天";
|
||||
} else if (newchajitian(startTime) > 1 && newchajitian(startTime) < 7) {
|
||||
//相差一天以上 七天之内 显示星期几
|
||||
showtimeString = getWeek(startTime);
|
||||
} else {
|
||||
format = new SimpleDateFormat("MM-dd");
|
||||
showtimeString = format.format(new Date(startTime));
|
||||
}
|
||||
|
||||
}
|
||||
return showtimeString;
|
||||
}
|
||||
|
||||
public static String getLastM(int total, int value) {
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM");
|
||||
Date date = new Date();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date); // 设置为当前时间
|
||||
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - (total - value));
|
||||
date = calendar.getTime();
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户生日计算年龄
|
||||
*/
|
||||
public static String getAgeByBirthday(Date birthday) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
if (cal.before(birthday)) {
|
||||
throw new IllegalArgumentException(
|
||||
"The birthDay is before Now.It's unbelievable!");
|
||||
}
|
||||
|
||||
int yearNow = cal.get(Calendar.YEAR);
|
||||
int monthNow = cal.get(Calendar.MONTH) + 1;
|
||||
int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
|
||||
|
||||
cal.setTime(birthday);
|
||||
int yearBirth = cal.get(Calendar.YEAR);
|
||||
int monthBirth = cal.get(Calendar.MONTH) + 1;
|
||||
int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
|
||||
|
||||
int age = yearNow - yearBirth;
|
||||
|
||||
if (monthNow <= monthBirth) {
|
||||
if (monthNow == monthBirth) {
|
||||
// monthNow==monthBirth
|
||||
if (dayOfMonthNow < dayOfMonthBirth) {
|
||||
age--;
|
||||
}
|
||||
} else {
|
||||
// monthNow>monthBirth
|
||||
age--;
|
||||
}
|
||||
}
|
||||
return age + "岁";
|
||||
}
|
||||
//获取当前年月日生成的唯一标识码
|
||||
public static String getTimeNumber(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
|
||||
return format.format(new Date(time));// 2012-10-03-23-41-31
|
||||
}
|
||||
//显示完整的年月日 时分秒
|
||||
public static String getTime(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
//显示完整的年月日 时分秒
|
||||
public static String getMinute(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("mm:ss");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
//显示完整的月日 时分
|
||||
public static String getComTime(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
//显示完整的年月日
|
||||
public static String getDateEN(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
//显示完整的年月日
|
||||
public static String getDateEND(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
//显示完整的年月日
|
||||
public static String getDateMon(long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("MM月dd日");
|
||||
return format.format(new Date(time));// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
// 获取当前年份
|
||||
public static String getYear(Long time) {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy");
|
||||
return format.format(new Date(time));
|
||||
}
|
||||
|
||||
public static long getDate(String timeStr) {
|
||||
long time = 0;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
|
||||
try {
|
||||
Date date = format.parse(timeStr);
|
||||
time = date.getTime();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return time / 1000;
|
||||
}
|
||||
|
||||
public static long getDateByString(String timeStr) {
|
||||
long time = 0;
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
try {
|
||||
Date date = format.parse(timeStr);
|
||||
time = date.getTime();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
public static String getTimeByString(String timeStr) {
|
||||
|
||||
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddhhmmss");
|
||||
Date date = null;
|
||||
try {
|
||||
date = sdf1.parse(timeStr);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
return sdf2.format(date);
|
||||
}
|
||||
|
||||
public static String getTimeByStr(String timeStr) {
|
||||
|
||||
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddhhmmss");
|
||||
Date date = null;
|
||||
try {
|
||||
date = sdf1.parse(timeStr);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return sdf2.format(date);
|
||||
}
|
||||
|
||||
|
||||
public static String setTimeByString(String timeStr) {
|
||||
|
||||
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
Date date = null;
|
||||
try {
|
||||
date = sdf1.parse(timeStr);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMddhhmmss");
|
||||
return sdf2.format(date);
|
||||
}
|
||||
|
||||
// 获取上午、下午时间
|
||||
public static String getHour(Long time) {
|
||||
String str;
|
||||
final Calendar mCalendar = Calendar.getInstance();
|
||||
mCalendar.setTimeInMillis(time);
|
||||
int apm = mCalendar.get(Calendar.AM_PM);
|
||||
SimpleDateFormat format = new SimpleDateFormat("hh:mm");
|
||||
String hour = format.format(time);
|
||||
|
||||
if (apm == 0) {
|
||||
str = "上午 " + hour;
|
||||
} else {
|
||||
str = "下午 " + hour;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static long newchajitian(Long lstartTime) {
|
||||
Calendar c1 = Calendar.getInstance();
|
||||
int year = c1.get(Calendar.YEAR);
|
||||
int yue = c1.get(Calendar.MONTH);
|
||||
int ri = c1.get(Calendar.DATE);
|
||||
c1.set(year, yue + 1, ri, 0, 0);
|
||||
Calendar c2 = Calendar.getInstance();
|
||||
int year_ = Integer.parseInt((getYear(lstartTime)));
|
||||
int yue_ = getYue(lstartTime);
|
||||
int ri_ = getDay(lstartTime);
|
||||
c2.set(year_, yue_, ri_, 0, 0);
|
||||
return getAbsDayDiff(c2, c1);
|
||||
}
|
||||
|
||||
public static int getDay(long time) {
|
||||
SimpleDateFormat format1 = new SimpleDateFormat("dd");
|
||||
String date1 = format1.format(new Date(time));
|
||||
return Integer.parseInt(date1);// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
public static int getYue(long time) {
|
||||
SimpleDateFormat format1 = new SimpleDateFormat("MM");
|
||||
String date1 = format1.format(new Date(time));
|
||||
return Integer.parseInt(date1);// 2012-10-03 23:41:31
|
||||
}
|
||||
|
||||
public static int getAbsDayDiff(Calendar calStart, Calendar calEnd) {
|
||||
Calendar start = (Calendar) calStart.clone();
|
||||
Calendar end = (Calendar) calEnd.clone();
|
||||
|
||||
start.set(start.get(Calendar.YEAR), start.get(Calendar.MONTH),
|
||||
start.get(Calendar.DATE), 0, 0, 0);
|
||||
start.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
end.set(end.get(Calendar.YEAR), end.get(Calendar.MONTH),
|
||||
end.get(Calendar.DATE), 0, 0, 0);
|
||||
end.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
return (int) ((end.getTimeInMillis() - start.getTimeInMillis()) / DAY_MILLSECONDS);
|
||||
}
|
||||
|
||||
//获取星期几
|
||||
public static String getWeek(long timeStamp) {
|
||||
int myDate;
|
||||
String week = null;
|
||||
Calendar cd = Calendar.getInstance();
|
||||
cd.setTime(new Date(timeStamp));
|
||||
myDate = cd.get(Calendar.DAY_OF_WEEK);
|
||||
// 获取指定日期转换成星期几
|
||||
if (myDate == 1) {
|
||||
week = "星期日";
|
||||
} else if (myDate == 2) {
|
||||
week = "星期一";
|
||||
} else if (myDate == 3) {
|
||||
week = "星期二";
|
||||
} else if (myDate == 4) {
|
||||
week = "星期三";
|
||||
} else if (myDate == 5) {
|
||||
week = "星期四";
|
||||
} else if (myDate == 6) {
|
||||
week = "星期五";
|
||||
} else if (myDate == 7) {
|
||||
week = "星期六";
|
||||
}
|
||||
return week;
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间转化为显示字符串
|
||||
*
|
||||
* @param timeStamp 单位为秒
|
||||
*/
|
||||
public static String getTimeStr(long timeStamp) {
|
||||
if (timeStamp == 0) return "";
|
||||
Calendar inputTime = Calendar.getInstance();
|
||||
inputTime.setTimeInMillis(timeStamp * 1000);
|
||||
Date currenTimeZone = inputTime.getTime();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (calendar.before(inputTime)) {
|
||||
//当前时间在输入时间之前
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
if (calendar.before(inputTime)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
if (calendar.before(inputTime)) {
|
||||
return "昨天";
|
||||
} else {
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
calendar.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
if (calendar.before(inputTime)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
|
||||
return sdf.format(currenTimeZone);
|
||||
} else {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("MM-dd");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间转化为聊天界面显示字符串
|
||||
*
|
||||
* @param timeStamp 单位为秒
|
||||
*/
|
||||
public static String getChatTimeStr(long timeStamp) {
|
||||
if (timeStamp == 0) return "";
|
||||
Calendar inputTime = Calendar.getInstance();
|
||||
inputTime.setTimeInMillis(timeStamp * 1000);
|
||||
Date currenTimeZone = inputTime.getTime();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (calendar.before(inputTime)) {
|
||||
//当前时间在输入时间之前
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
if (calendar.before(inputTime)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
||||
if (calendar.before(inputTime)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
|
||||
return "昨天 " + sdf.format(currenTimeZone);
|
||||
} else {
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
calendar.set(Calendar.MONTH, Calendar.JANUARY);
|
||||
if (calendar.before(inputTime)) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("M月d日" + " HH:mm");
|
||||
return sdf.format(currenTimeZone);
|
||||
} else {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日" + " HH:mm");
|
||||
return sdf.format(currenTimeZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int getYear() {
|
||||
return Calendar.getInstance().get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
public static int getMonth() {
|
||||
return Calendar.getInstance().get(Calendar.MONTH) + 1;
|
||||
}
|
||||
|
||||
public static int getCurrentMonthDay() {
|
||||
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转为时间戳
|
||||
*/
|
||||
public static long getStringToDate(String time) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
|
||||
Date date = new Date();
|
||||
try {
|
||||
date = simpleDateFormat.parse(time);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
//获得当前日期与本周一相差的天数
|
||||
public static int getMondayPlus() {
|
||||
Calendar cd = Calendar.getInstance();
|
||||
// 获得今天是一周的第几天,星期日是第一天,星期二是第二天......
|
||||
int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK);
|
||||
if (dayOfWeek == 1) {
|
||||
return -6;
|
||||
} else {
|
||||
return 2 - dayOfWeek;
|
||||
}
|
||||
}
|
||||
|
||||
//获得本周星期一的日期
|
||||
public static Calendar getCurrentMonday() {
|
||||
int mondayPlus = getMondayPlus();
|
||||
GregorianCalendar currentDate = new GregorianCalendar();
|
||||
currentDate.add(GregorianCalendar.DATE, mondayPlus);
|
||||
Date monday = currentDate.getTime();
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(monday);
|
||||
return c;
|
||||
}
|
||||
|
||||
// 上/下 一月
|
||||
public static String getLastOrNextMonth(String timeStr, int value) {
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月");
|
||||
Date date = new Date();
|
||||
if (!timeStr.equals("本月")) {
|
||||
try {
|
||||
date = dateFormat.parse(timeStr);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date); // 设置为当前时间
|
||||
calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - value);
|
||||
date = calendar.getTime();
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
// 上/下 一周
|
||||
public static String getLastOrNextWeek(String timeStr, int value) {
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年");
|
||||
Date date = new Date();
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (!timeStr.equals("本周")) {
|
||||
try {
|
||||
date = dateFormat.parse(timeStr.substring(0, timeStr.indexOf("年") + 1));
|
||||
calendar.setTime(date); // 设置为当前时间
|
||||
calendar.set(Calendar.WEEK_OF_YEAR, Integer.parseInt(timeStr
|
||||
.substring(timeStr.indexOf("年") + 1, timeStr.indexOf("周"))) - value);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
calendar.setTime(date); // 设置为当前时间
|
||||
calendar.set(Calendar.WEEK_OF_YEAR, calendar.get(Calendar.WEEK_OF_YEAR) - value);
|
||||
}
|
||||
date = calendar.getTime();
|
||||
if (calendar.get(Calendar.WEEK_OF_YEAR) > 9) {
|
||||
return dateFormat.format(date) + calendar.get(Calendar.WEEK_OF_YEAR) + "周";
|
||||
} else {
|
||||
return dateFormat.format(date) + "0" + calendar.get(Calendar.WEEK_OF_YEAR) + "周";
|
||||
}
|
||||
}
|
||||
|
||||
// 上/下 一日
|
||||
public static String getLastOrNextDay(String timeStr, int value) {
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
Date date = new Date();
|
||||
if (!timeStr.equals("今日")) {
|
||||
try {
|
||||
date = dateFormat.parse(timeStr);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date); // 设置为当前时间
|
||||
calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - value);
|
||||
date = calendar.getTime();
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
// 是否是今日
|
||||
public static Boolean isToday(String timeStr) {
|
||||
return getDateEN(System.currentTimeMillis()).equals(timeStr);
|
||||
}
|
||||
//
|
||||
// // 是否是本周
|
||||
// public static Boolean isTswk(String timeStr) {
|
||||
//
|
||||
// Calendar calendar = Calendar.getInstance();
|
||||
// int year = Integer.parseInt(timeStr.substring(0, timeStr.indexOf("年")));
|
||||
// int week = Integer.parseInt(timeStr
|
||||
// .substring(timeStr.indexOf("年") + 1, timeStr.indexOf("周")));
|
||||
//
|
||||
// return calendar.get(Calendar.YEAR) == year && calendar.get(Calendar.WEEK_OF_YEAR) == week;
|
||||
// }
|
||||
|
||||
// 是否是本月
|
||||
public static Boolean isTsM(String timeStr) {
|
||||
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月");
|
||||
String nowTime = dateFormat.format(new Date(System.currentTimeMillis()));
|
||||
|
||||
return timeStr.equals(nowTime);
|
||||
}
|
||||
|
||||
|
||||
public static String getDisparity(String timeStamp) {
|
||||
Long target = getDateByString(timeStamp);
|
||||
Long now = System.currentTimeMillis();
|
||||
if (target < now) {
|
||||
return "已截止";
|
||||
}
|
||||
Long l = target - now;
|
||||
long Minute = (l / (1000 * 60));
|
||||
long day = (l / (1000 * 60 * 60 * 24));
|
||||
long min = Minute - (day * 60 * 24);
|
||||
long hour = min / 60;
|
||||
long minute = min - (hour * 60);
|
||||
return day + "天" + hour + ":" + minute + "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package com.android.api.encrytion;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.Key;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public final class UtilEncrypt {
|
||||
|
||||
/**
|
||||
* 默认密钥,实际项目中可配置注入或数据库读取
|
||||
*/
|
||||
private final static String DEFAULT_KEY = "asla01slajf1ALlsdaf0987654321";
|
||||
|
||||
/**
|
||||
* 对字符串进行默认加密
|
||||
*/
|
||||
public static String encrypt(String str) {
|
||||
return encrypt(str, DEFAULT_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串加密
|
||||
*/
|
||||
public static String decrypt(String str) {
|
||||
return decrypt(str, DEFAULT_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串加密
|
||||
*/
|
||||
public static String encrypt(String plainText, String key) {
|
||||
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
bytes = plainText.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
byte[] encryptedBytes = getCipher(Cipher.ENCRYPT_MODE, key).doFinal(bytes);
|
||||
return UtilHex.bytes2HexString(encryptedBytes);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对字符串解密
|
||||
*/
|
||||
public static String decrypt(String encryptedText, String key) {
|
||||
byte[] arr = UtilHex.hexString2Bytes(encryptedText);
|
||||
try {
|
||||
byte[] decryptedBytes = getCipher(Cipher.DECRYPT_MODE, key).doFinal(arr);
|
||||
return new String(decryptedBytes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Cipher getCipher(int mode, String key) {
|
||||
// Security.addProvider(new com.sun.crypto.provider.SunJCE());
|
||||
// Security.addProvider(new Provider.SunJCE());
|
||||
if (key == null) {
|
||||
key = DEFAULT_KEY;
|
||||
}
|
||||
byte[] arrBTmp = null;
|
||||
try {
|
||||
arrBTmp = key.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
// 创建一个空的length位字节数组(默认值为0)
|
||||
byte[] arrB = new byte[16];
|
||||
|
||||
// 将原始字节数组转换为8位
|
||||
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
|
||||
arrB[i] = arrBTmp[i];
|
||||
}
|
||||
// 生成密钥
|
||||
Key theKey = new javax.crypto.spec.SecretKeySpec(arrB, "AES");
|
||||
|
||||
// 生成Cipher对象,指定其支持的DES算法
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(mode, theKey);
|
||||
return cipher;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String value = encrypt("heartbeat.akrdinfo.cn");
|
||||
System.out.println(value);
|
||||
// System.out.println(decrypt("7ae044016890d6862e2e343f9b735db1464f0b63c251cce2e9855af9c3c7f6be"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.android.api.encrytion;
|
||||
|
||||
/**
|
||||
* 16进制转换工具
|
||||
*
|
||||
* @author wulh create on 2018/5/20.
|
||||
*/
|
||||
public final class UtilHex {
|
||||
|
||||
/**
|
||||
* 16进制字符串转为字节数组
|
||||
* @param hexStr 长度必须为偶数,每个字节用两个字符表达
|
||||
* @return 对应字节数组
|
||||
*/
|
||||
public static byte[] hexString2Bytes(String hexStr) {
|
||||
if(hexStr == null || hexStr.length() == 0 || hexStr.length() % 2 > 0) {
|
||||
throw new IllegalArgumentException("参数长度必须为偶数");
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[hexStr.length() / 2];
|
||||
for(int i = 0, len = bytes.length; i < len; i++) {
|
||||
bytes[i] = (byte) (0xFF & Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 16进制字符串转为字节数组
|
||||
* @param hexStr 长度必须为偶数,每个字节用两个字符表达
|
||||
* @return 对应字节数组
|
||||
*/
|
||||
public static String bytes2HexString(byte[] bytes) {
|
||||
if(bytes == null || bytes.length == 0) {
|
||||
throw new IllegalArgumentException("参数必须非空");
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(byte b : bytes) {
|
||||
String s = Integer.toHexString(0xFF & b);
|
||||
if(s.length() == 1) {
|
||||
s = "0" + s;
|
||||
}
|
||||
sb.append(s);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.android.api.response;
|
||||
|
||||
import com.android.nebulasdk.bean.BaseValue;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by Administrator on 2018/5/11 0011.
|
||||
*/
|
||||
|
||||
public class BaseResponse implements Serializable {
|
||||
|
||||
public String msg;
|
||||
public int code;
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.android.api.response;
|
||||
|
||||
|
||||
public class EventResponse extends BaseResponse {
|
||||
private String data;
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user