Commit e1e4bbb3 authored by chenyuling's avatar chenyuling

"接口测试"

parents
Pipeline #1445 canceled with stages
*.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
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>
\ No newline at end of file
<?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="GRADLE" />
<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>
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="SuppressKotlinCodeStyleNotification">
<option name="disableForAll" value="true" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
/build
\ No newline at end of file
plugins {
id 'com.android.application'
}
apply plugin:'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
signingConfigs {
release {
storeFile file('../srthinker.jks')
storePassword 'srthinker'
keyAlias 'srthinker'
keyPassword 'srthinker'
}
}
namespace 'com.srthinker.statinfo'
compileSdk 32
defaultConfig {
applicationId "com.srthinker.statinfo"
minSdk 24
targetSdk 32
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
viewBinding{
enabled = true
}
applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName
if (variant.buildType.name == 'release') {
fileName = "${appName}-V${defaultConfig.versionName}-release-${releaseTime()}.apk"
} else if (variant.buildType.name == 'debug') {
fileName = "${appName}-V${defaultConfig.versionName}-debug.-${releaseTime()}apk"
} else {
fileName = "${appName}-V${defaultConfig.versionName}-other-${releaseTime()}.apk"
}
outputFileName = fileName
}
}
}
}
def releaseTime() {
return new Date().format("yyyyMMdd_HHmmss", TimeZone.getDefault())
}
ext.appName = "statinfo"
def dbflow_version = "4.2.4"
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.core:core-ktx:1.7.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.github.bumptech.glide:glide:4.12.0' //4.9.0
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation 'com.github.JessYanCoding:AndroidAutoSize:v1.2.1'
implementation 'com.orhanobut:logger:2.2.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.alibaba:fastjson:1.2.75'
annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:$dbflow_version"
implementation "com.github.Raizlabs.DBFlow:dbflow-core:$dbflow_version"
implementation "com.github.Raizlabs.DBFlow:dbflow:$dbflow_version"
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
implementation 'org.apache.commons:commons-lang3:3.9'
implementation 'org.slf4j:slf4j-android:1.7.30'
implementation 'org.slf4j:slf4j-api:1.7.30'
implementation 'org.java-websocket:Java-WebSocket:1.5.1'
implementation 'org.bouncycastle:bcprov-jdk15on:1.68'
}
\ No newline at end of file
# 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
\ No newline at end of file
package com.srthinker.statinfo;
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.srthinker.statinfo", appContext.getPackageName());
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 安装APK权限,需要在程序中动态申请,并且不同于外部存储读写权限申请 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:name=".uis.MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.StatInfo"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<meta-data
android:name="design_width_in_dp"
android:value="960" />
<meta-data
android:name="design_height_in_dp"
android:value="540" /> <!-- fileprovider名称在安装时传递给系统安装程序 -->
<!--<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/autoupdate" />
</provider>-->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<activity
android:name=".uis.MainActivity"
android:configChanges="keyboardHidden|orientation"
android:exported="true"
android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<!--<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />-->
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".uis.GroupActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".uis.FlashActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
\ No newline at end of file
package com.srthinker.statinfo.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.databinding.ItemEnterBinding;
import java.util.List;
public class EnterAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "EnterAdapter";
private final Context context;
private List<PersonEntity> personEntities;
public EnterAdapter(Context context, List<PersonEntity> pData){
this.context = context;
this.personEntities = pData;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemEnterBinding binding = ItemEnterBinding.inflate(LayoutInflater.from(context), parent, false);
return new ItemHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemHolder itemHolder = (ItemHolder) holder;
PersonEntity peopleBean = personEntities.get(position);
// Log.i(TAG, "onBindViewHolder: peopleBeans.size="+ personEntities.size());
if (peopleBean!=null){
// Log.i(TAG, "onBindViewHolder: name="+peopleBean.getPerson_name());
itemHolder.mBinding.tvInfo.setText(peopleBean.getTimestamp()+" "+peopleBean.getPerson_name());
}
}
@Override
public int getItemCount() {
return personEntities !=null&& personEntities.size()>0? personEntities.size():0;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private final com.srthinker.statinfo.databinding.ItemEnterBinding mBinding;
public ItemHolder(ItemEnterBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
}
public void setDataList(List<PersonEntity> peopleBeans){
//Log.i(TAG, "setDataList: 更新列表,size="+peopleBeans.size());
// this.peopleBeans=new ArrayList<>();
this.personEntities.clear();
this.personEntities.addAll(peopleBeans);
this.notifyDataSetChanged();
}
public List<PersonEntity> getDataList(){
return personEntities;
}
}
package com.srthinker.statinfo.adapter;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.bean.GroupBean;
import com.srthinker.statinfo.databinding.ItemGroupBinding;
import com.srthinker.statinfo.util.common.KeyBoardUtil;
import com.srthinker.statinfo.util.common.SharedUtil;
import com.srthinker.statinfo.util.common.StatusBarUtil;
import java.util.ArrayList;
public class GroupAdapter extends RecyclerView.Adapter {
private final Context context;
private ArrayList<GroupBean> groupBeans;
private final Activity activity;
public GroupAdapter(Context context, ArrayList<GroupBean> groupBeans){
this.context = context;
activity = (Activity) context;
this.groupBeans = groupBeans;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemGroupBinding binding = ItemGroupBinding.inflate(LayoutInflater.from(context), parent, false);
return new ItemHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemHolder itemHolder = (ItemHolder) holder;
GroupBean groupBean = groupBeans.get(position);
if (groupBean!=null){
itemHolder.mBinding.llItem.setBackgroundColor(context.getResources().getColor(groupBean.getColor()));
itemHolder.mBinding.tvDesc.setText(groupBean.getDesc());
itemHolder.mBinding.etNumber.setText(groupBean.getNumber()+"");
KeyBoardUtil.SoftKeyBoardListener.setListener(activity, new KeyBoardUtil.SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
@Override
public void keyBoardShow(int height) {
}
@Override
public void keyBoardHide(int height) {
itemHolder.mBinding.etNumber.clearFocus();
StatusBarUtil.hideSystemUI(activity);
int groupNumber = Integer.parseInt(itemHolder.mBinding.etNumber.getText().toString());
SharedUtil.getInstance(context).writeShared(groupBean.getType(),groupNumber);
}
});
}
}
@Override
public int getItemCount() {
return groupBeans!=null&&groupBeans.size()>0?groupBeans.size():0;
}
private class ItemHolder extends RecyclerView.ViewHolder {
private final com.srthinker.statinfo.databinding.ItemGroupBinding mBinding;
public ItemHolder(ItemGroupBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
}
public void setDataList(ArrayList<GroupBean> groupBeans){
this.groupBeans = groupBeans;
notifyDataSetChanged();
}
}
package com.srthinker.statinfo.adapter;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import com.srthinker.statinfo.uis.fragment.group.TabGroupFragment;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Objects;
public class GroupPagerAdapter extends FragmentPagerAdapter {
private final LinkedHashMap<String, Integer> groupMap;
private ArrayList<String> titleList;
//private ArrayList<TabGroupFragment> fragmentList = new ArrayList<>();
private final HashMap<Integer,TabGroupFragment> fragmentHashMap = new HashMap<>();
private String TAG = "GroupPagerAdapter";
public GroupPagerAdapter(@NonNull FragmentManager fm, LinkedHashMap<String,Integer> groupMap) {
super(fm);
this.groupMap = groupMap;
if (groupMap!=null){
titleList = new ArrayList<>(groupMap.keySet());
}
}
@NonNull
@Override
public Fragment getItem(int position) {
//Log.i(TAG, "getItem: position="+position);
if (titleList!=null && titleList.size()>0) {
if (fragmentHashMap.containsKey(position)) {
return Objects.requireNonNull(fragmentHashMap.get(position));
}else{
TabGroupFragment fragment = TabGroupFragment.getInstance(groupMap.get(titleList.get(position)));
fragmentHashMap.put(position,fragment);
return fragment;
}
}
return null;
}
@Override
public int getCount() {
return titleList!=null&&titleList.size()>0?titleList.size():0;
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return titleList!=null&&titleList.size()>0?titleList.get(position):null;
}
}
package com.srthinker.statinfo.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.databinding.ItemLeaveBinding;
import java.util.List;
public class LeaveAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "LeaveAdapter";
private final Context context;
private List<PersonEntity> peopleBeans;
public LeaveAdapter(Context context, List<PersonEntity> peopleBeans){
this.context = context;
this.peopleBeans = peopleBeans;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemLeaveBinding binding = ItemLeaveBinding.inflate(LayoutInflater.from(context), parent, false);
return new ItemHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemHolder itemHolder = (ItemHolder) holder;
PersonEntity peopleBean = peopleBeans.get(position);
if (peopleBean != null) {
itemHolder.mBinding.tvInfo.setText(peopleBean.getTimestamp()+" "+peopleBean.getPerson_name());
}
}
@Override
public int getItemCount() {
return peopleBeans!=null&&peopleBeans.size()>0?peopleBeans.size():0;
}
private static class ItemHolder extends RecyclerView.ViewHolder {
private final com.srthinker.statinfo.databinding.ItemLeaveBinding mBinding;
public ItemHolder(ItemLeaveBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
}
public void setDataList(List<PersonEntity> peopleBeans){
//this.peopleBeans = peopleBeans;
this.peopleBeans.clear();
this.peopleBeans.addAll(peopleBeans);
//Log.i(TAG, "setDataList: size="+this.peopleBeans.size());
this.notifyDataSetChanged();
}
public List<PersonEntity> getDataList(){
return this.peopleBeans;
}
}
package com.srthinker.statinfo.adapter;
import android.content.Context;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.databinding.ItemSelectGroupBinding;
import java.util.ArrayList;
import java.util.List;
public class PersonGroupSAdapter extends RecyclerView.Adapter {
private final Context context;
private List<PersonEntity> personEntities = new ArrayList<>();
private SparseBooleanArray mSelectedPositions = new SparseBooleanArray();
private boolean mIsSelectable =false;
public PersonGroupSAdapter(Context context, List<PersonEntity> personEntities){
this.context = context;
this.personEntities = personEntities;
}
public void setDataList(List<PersonEntity> personEntities){
this.personEntities = personEntities;
mSelectedPositions = new SparseBooleanArray();
notifyDataSetChanged();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
ItemSelectGroupBinding binding = ItemSelectGroupBinding.inflate(LayoutInflater.from(context), parent, false);
return new ItemHolder(binding);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemHolder itemHolder = (ItemHolder) holder;
PersonEntity person = personEntities.get(position);
if (person!=null){
itemHolder.mBinding.tvPersonName.setText(person.getPerson_name());
itemHolder.mBinding.tvPersonName.setSelected(isItemChecked(position));
itemHolder.mBinding.llItem.setOnClickListener(v->{
if (isItemChecked(position)){
itemHolder.mBinding.tvPersonName.setSelected(false);
setItemChecked(position,false);
}else{
itemHolder.mBinding.tvPersonName.setSelected(true);
setItemChecked(position,true);
}
});
}
}
@Override
public int getItemCount() {
return personEntities!=null&&personEntities.size()>=0?personEntities.size():0;
}
//设置给定位置条目的选择状态
private void setItemChecked(int position, boolean isChecked) {
mSelectedPositions.put(position, isChecked);
}
//根据位置判断条目是否选中
private boolean isItemChecked(int position) {
return mSelectedPositions.get(position);
}
//根据位置判断条目是否可选
private boolean isSelectable() {
return mIsSelectable;
}
//设置给定位置条目的可选与否的状态
private void setSelectable(boolean selectable) {
mIsSelectable = selectable;
}
//获取选中的结果
public List<PersonEntity> getSelectedItem(){
List<PersonEntity> selectList = new ArrayList<>();
if (personEntities!=null){
for (int i = 0; i < personEntities.size(); i++) {
if (isItemChecked(i)){
selectList.add(personEntities.get(i));
}
}
}
return selectList;
}
private class ItemHolder extends RecyclerView.ViewHolder {
private final com.srthinker.statinfo.databinding.ItemSelectGroupBinding mBinding;
public ItemHolder(ItemSelectGroupBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
}
}
package com.srthinker.statinfo.api.kuangshi;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.auth.AuthApi;
import com.srthinker.statinfo.api.kuangshi.api.auth.bean.LoginResp;
import com.srthinker.statinfo.api.kuangshi.api.auth.impl.AuthApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.device.DeviceApi;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.DeviceStatusResp;
import com.srthinker.statinfo.api.kuangshi.api.device.impl.DeviceApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.group.GroupApi;
import com.srthinker.statinfo.api.kuangshi.api.group.impl.GroupApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.person.PersonApi;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.FaceListItem;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonBean;
import com.srthinker.statinfo.api.kuangshi.api.person.impl.PersonApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.schedule.ScheduleApi;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleJsonBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleListRuleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleListRuleJsonBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.impl.ScheduleApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.subscribe.SubscribeApi;
import com.srthinker.statinfo.api.kuangshi.api.subscribe.impl.SubscribeApiImpl;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import com.srthinker.statinfo.api.kuangshi.utils.DigestUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ApiDemo {
public static void main(String[] args) throws Exception {
String username = "admin";
//TODO 请替换下面的设备ip & 登录密码
String serverIp = "192.168.1.170";
String password = "admin123456";
String apiServerUrlPrefix = "http://" + serverIp;
//以设备为单位,每个设备都需要创建单独的DefaultApiClient
DefaultApiClient apiClient = new DefaultApiClient(apiServerUrlPrefix);
//一个设备创建的api,都应该用同一个apiClient
AuthApi authApi = new AuthApiImpl(apiClient);
DeviceApi deviceApi = new DeviceApiImpl(apiClient);
ScheduleApi scheduleApi = new ScheduleApiImpl(apiClient);
PersonApi personApi = new PersonApiImpl(apiClient);
GroupApi groupApi = new GroupApiImpl(apiClient);
SubscribeApi subscribeApi = new SubscribeApiImpl(apiClient);
//进行设备登录
// LoginResp loginResp = authApi.login("admin", "a12345");
LoginResp loginResp = authApi.login(username, password);
if(loginResp.getStatus() != 200) {
//登录出错,打印错误信息
System.out.println(JSONObject.toJSONString(loginResp));
return;
}
//获取设备状态
DeviceStatusResp deviceStatusResp = deviceApi.status();
System.out.println(JSONObject.toJSONString(deviceStatusResp));
// //添加门禁计划 - 通过json格式添加
// ScheduleJsonBean scheduleBeanJson = mockScheduleByJson();
// scheduleBeanJson = scheduleApi.addScheduleItemByJson(scheduleBeanJson);
// System.out.println(JSONObject.toJSONString(scheduleBeanJson));
// //添加门禁计划 - 通过crond格式添加
// ScheduleCrondBean scheduleBeanCrond = mockScheduleByCrond();
// scheduleBeanCrond = scheduleApi.addScheduleItemByCrond(scheduleBeanCrond);
// System.out.println(JSONObject.toJSONString(scheduleBeanCrond));
// //添加人员组
// GroupBean groupBean = new GroupBean();
// groupBean.setGroupName("组名称_" + System.currentTimeMillis());
// groupBean.setScheduleId(scheduleBeanCrond.getId());
// groupBean = groupApi.add(groupBean);
// //添加人员
// PersonBean personBean = mockPerson(loginResp.getSessionId(), groupBean.getId());
// personApi.add(personBean);
//HTTP上传文件升级
// File file = new File("/Users/liuqingliang/Downloads/test_img.jpeg");
// FirmwareBean firmwareBean = deviceApi.firmware(file);
// System.out.println(JSONObject.toJSONString(firmwareBean));
// //OTA升级接口
// FirmwareBean fb = deviceApi.firmwareOta("http://xxxxxx/xxxx.bin", "");
// System.out.println(JSONObject.toJSONString(fb));
//设置第三方服务器推送配置
// subscribeApi.push("http://xxxxxxx:8080/xxxx", true, "POST");
//开始websocket client, 进行消息订阅
Map<String, String> headers = new HashMap<>();
String wsServerUrl = String.format("ws://%s%s?session_id=%s", serverIp, "/api/subscribe", loginResp.getSessionId());
System.out.println(wsServerUrl);
MyWebSocketClient myWebSocketClient = new MyWebSocketClient(wsServerUrl);
// myWebSocketClient.send("hello");
Thread.sleep(600000);
}
public static PersonBean mockPerson(String sessionId, String groupId) {
PersonBean personBean = new PersonBean();
personBean.setRecognitionType("visitor");
personBean.setPersonName("人员姓名_" + System.currentTimeMillis());
personBean.setPasswordEncryptType("plain");
//TODO 加密的demo
// personBean.setPassword(DigestUtils.aesEncrypt("123456", sessionId));
personBean.setPassword("123456");
personBean.setIdNumber(DigestUtils.aesEncrypt("321345454", sessionId));
personBean.setCardNumber("cn" + (System.currentTimeMillis() % 10000));
personBean.setGroupList(Arrays.asList(new String[]{groupId}));
//获取图片
FaceListItem flt = new FaceListItem(0, getImageData("/Users/liuqingliang/Downloads/test_img.jpeg"));
personBean.setFaceList(Arrays.asList(flt));
personBean.setVisitBeginTime(new Date().toString());
personBean.setVisitEndTime(new Date(System.currentTimeMillis() + 100000).toString());
return personBean;
}
public static String getImageData(String filePath) {
try {
byte[] cb = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
cb = Files.readAllBytes(Paths.get(filePath));
}else{
InputStream inputStream = new FileInputStream(new File(filePath));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
cb = outputStream.toByteArray();
inputStream.close();
outputStream.close();
}
String content = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
content = new String( Base64.getEncoder().encodeToString(cb));
}else{
content = android.util.Base64.encodeToString(cb, android.util.Base64.DEFAULT);
}
return content;
} catch (Exception e) {
throw new RuntimeException("");
}
}
public static ScheduleCrondBean mockScheduleByCrond() {
ScheduleCrondBean scheduleBean = new ScheduleCrondBean();
scheduleBean.setScheduleName("JSON时间计划_" + System.currentTimeMillis());
scheduleBean.setScheduleListType("crond");
List<ScheduleListRuleCrondBean> scheduleList = new ArrayList<>();
ScheduleListRuleCrondBean scheduleListRuleCrondBean = new ScheduleListRuleCrondBean();
scheduleListRuleCrondBean.setType("workday");
scheduleListRuleCrondBean.setRule("8:00-21:00,21:00-22:00 * * 1 *");
scheduleList.add(scheduleListRuleCrondBean);
scheduleListRuleCrondBean = new ScheduleListRuleCrondBean();
scheduleListRuleCrondBean.setType("holiday");
scheduleListRuleCrondBean.setRule("8:00-21:00,21:00-22:00 9 10 * *");
scheduleList.add(scheduleListRuleCrondBean);
scheduleBean.setScheduleList(scheduleList);
return scheduleBean;
}
public static ScheduleJsonBean mockScheduleByJson() {
ScheduleJsonBean scheduleBean = new ScheduleJsonBean();
scheduleBean.setScheduleName("JSON时间计划_" + System.currentTimeMillis());
scheduleBean.setScheduleListType("json");
List<ScheduleListRuleJsonBean> scheduleList = new ArrayList<>();
ScheduleListRuleJsonBean scheduleListRuleJsonBean = new ScheduleListRuleJsonBean();
scheduleListRuleJsonBean.setType("workday");
HashMap<String, String> rules = new HashMap<>();
rules.put("1", "00:02-11:59,14:00-23:59");
rules.put("2", "00:20-03:20,08:00-16:59,17:00-23:59");
rules.put("3", "09:20-16:20");
rules.put("4", "09:20-16:20");
rules.put("5", "09:20-16:20");
rules.put("6", "09:20-16:20");
rules.put("7", "09:20-16:20");
scheduleListRuleJsonBean.setRule(rules);
scheduleList.add(scheduleListRuleJsonBean);
scheduleListRuleJsonBean = new ScheduleListRuleJsonBean();
scheduleListRuleJsonBean.setType("holiday");
rules = new HashMap<>();
rules.put("20210330", "00:02-11:59,14:00-23:59");
rules.put("20210403", "09:20-16:20");
scheduleListRuleJsonBean.setRule(rules);
scheduleList.add(scheduleListRuleJsonBean);
scheduleBean.setScheduleList(scheduleList);
return scheduleBean;
}
}
package com.srthinker.statinfo.api.kuangshi;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class MyWebSocketClient extends WebSocketClient {
Logger logger = LoggerFactory.getLogger(MyWebSocketClient.class);
public MyWebSocketClient(String serverUrl) {
super(URI.create(serverUrl));
this.waitConnect();
}
public void waitConnect(){
try {
this.connectBlocking();
} catch (InterruptedException e) {
logger.error(e.getMessage(),e);
}
}
@Override
public void onOpen(ServerHandshake serverHandshake) {
logger.info("---------MyWebSocketClient onOpen---------------");
}
@Override
public void onMessage(String s) {
logger.info("---------MyWebSocketClient onMessage---------------");
System.out.println(s);
//收到的消息内容,可根据协议文档进行json数据解析
}
@Override
public void onClose(int i, String s, boolean b) {
logger.info("---------MyWebSocketClient onClose---------------");
}
@Override
public void onError(Exception e) {
logger.info("---------MyWebSocketClient onError---------------");
}
}
package com.srthinker.statinfo.api.kuangshi.api;
import java.util.List;
public class ErrorResp {
private List<ErrorsBean> errors;
public List<ErrorsBean> getErrors() {
return errors;
}
public void setErrors(List<ErrorsBean> errors) {
this.errors = errors;
}
public static class ErrorsBean {
private int status;
private SourceBean source;
private String title;
private String detail;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public SourceBean getSource() {
return source;
}
public void setSource(SourceBean source) {
this.source = source;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public static class SourceBean {
private String pointer;
public String getPointer() {
return pointer;
}
public void setPointer(String pointer) {
this.pointer = pointer;
}
}
}
}
package com.srthinker.statinfo.api.kuangshi.api.auth;
import com.srthinker.statinfo.api.kuangshi.api.auth.bean.LoginResp;
/**
* 描述:认证管理类接口
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public interface AuthApi {
/**
* 登录接口
* @param username 登录用户名
* @param password 用户密码(明文)
* @return
*/
LoginResp login(String username, String password);
String auth(String username);
}
package com.srthinker.statinfo.api.kuangshi.api.auth.bean;
/**
* 描述:TODO
*
* @author:
* Date: 2021/3/8
*/
public class LoginLockInfo {
/**
* 是否已锁定
*/
private boolean locked;
/**
* 剩余重试次数
*/
private int retryTime;
/**
* 锁定后剩余解锁时间,单位为秒
*/
private int unlockTime;
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public int getRetryTime() {
return retryTime;
}
public void setRetryTime(int retryTime) {
this.retryTime = retryTime;
}
public int getUnlockTime() {
return unlockTime;
}
public void setUnlockTime(int unlockTime) {
this.unlockTime = unlockTime;
}
}
package com.srthinker.statinfo.api.kuangshi.api.auth.bean;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 描述:登录接口返回
*
* @author: liuqingliang
* Date: 2021/3/8
*/
public class LoginResp {
/**
* 校验结果,200成功,401失败
*/
private int status;
/**
* 保存作为后续请求的凭证
*/
@JSONField(name = "session_id")
private String sessionId;
/**
* 只有失败后才会返回该字段
*/
private LoginLockInfo loginLockInfo;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public LoginLockInfo getLoginLockInfo() {
return loginLockInfo;
}
public void setLoginLockInfo(LoginLockInfo loginLockInfo) {
this.loginLockInfo = loginLockInfo;
}
}
package com.srthinker.statinfo.api.kuangshi.api.auth.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.auth.AuthApi;
import com.srthinker.statinfo.api.kuangshi.api.auth.bean.LoginResp;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import com.srthinker.statinfo.api.kuangshi.utils.DigestUtils;
import java.util.HashMap;
import java.util.Map;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class AuthApiImpl implements AuthApi {
private static final String CHALLENGE_URL = "/api/auth/login/challenge";
private static final String LOGIN_URL = "/api/auth/login";
private DefaultApiClient httpClient;
public AuthApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public LoginResp login(String username, String password) {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("username", username);
String response = httpClient.doGet(CHALLENGE_URL, queryParams);
JSONObject challengeJsonResp = JSONObject.parseObject(response);
if (challengeJsonResp != null) {
JSONObject jsonBody = new JSONObject();
String sessionId = challengeJsonResp.getString("session_id");
jsonBody.put("session_id", sessionId);
jsonBody.put("username", username);
// set password
String pwd = DigestUtils.sha256(String.format("%s%s%s", password, challengeJsonResp.getString("salt"), challengeJsonResp.getString("challenge")));
jsonBody.put("password", pwd);
//set ciphertext
String ciphertext = DigestUtils.aesEncrypt(password, sessionId);
jsonBody.put("ciphertext", ciphertext);
String resp = httpClient.doPostJson(LOGIN_URL, jsonBody.toJSONString());
LoginResp loginResp = JSONObject.parseObject(resp, LoginResp.class);
if (loginResp != null) {
if(loginResp.getStatus() == 200) {
//登录成功,将sessionid写入cookie
if (loginResp != null) {
httpClient.setCoolie(String.format("sessionID=%s", loginResp.getSessionId()));
}
}
}
return loginResp;
}
return null;
}
@Override
public String auth(String username) {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("username", username);
String response = httpClient.doGet(CHALLENGE_URL, queryParams);
JSONObject challengeJsonResp = JSONObject.parseObject(response);
return challengeJsonResp.getString("session_id");
}
}
package com.srthinker.statinfo.api.kuangshi.api.device;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.DeviceStatusResp;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.FirmwareBean;
import java.io.File;
/**
* 描述:设备管理类接口
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public interface DeviceApi {
/**
* 获取设备状态信息
* @return
*/
DeviceStatusResp status();
/**
* 上传升级文件
* @param file
* @return
*/
FirmwareBean firmware(File file);
/**
* OTA升级接口
* @param otaUri
* @param md5
* @return
*/
FirmwareBean firmwareOta(String otaUri, String md5);
}
package com.srthinker.statinfo.api.kuangshi.api.device.bean;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 描述:获取设备状态接口返回
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class DeviceStatusResp {
/**
* 设备型号
*/
@JSONField(name = "model_spec")
private String modelSpec;
/**
* 设备序列号
*/
@JSONField(name = "serial_no")
private String serialNo;
/**
* 设备硬件地址
*/
@JSONField(name = "mac_str")
private String macStr;
/**
* 固件版本
*/
@JSONField(name = "firmware_version")
private String firmwareVersion;
/**
* 固件发布日期
*/
@JSONField(name = "firmware_date")
private String firmwareDate;
/**
* Web api版本
*/
@JSONField(name = "api_version")
private String apiVersion;
/**
* 设备人脸库版本
*/
@JSONField(name = "face_version")
private String faceVersion;
public String getModelSpec() {
return modelSpec;
}
public void setModelSpec(String modelSpec) {
this.modelSpec = modelSpec;
}
public String getSerialNo() {
return serialNo;
}
public void setSerialNo(String serialNo) {
this.serialNo = serialNo;
}
public String getMacStr() {
return macStr;
}
public void setMacStr(String macStr) {
this.macStr = macStr;
}
public String getFirmwareVersion() {
return firmwareVersion;
}
public void setFirmwareVersion(String firmwareVersion) {
this.firmwareVersion = firmwareVersion;
}
public String getFirmwareDate() {
return firmwareDate;
}
public void setFirmwareDate(String firmwareDate) {
this.firmwareDate = firmwareDate;
}
public String getApiVersion() {
return apiVersion;
}
public void setApiVersion(String apiVersion) {
this.apiVersion = apiVersion;
}
public String getFaceVersion() {
return faceVersion;
}
public void setFaceVersion(String faceVersion) {
this.faceVersion = faceVersion;
}
}
package com.srthinker.statinfo.api.kuangshi.api.device.bean;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class FirmwareBean {
/**
* 获取升级状态的uri
*/
private String href;
/**
* http 方法
*/
private String method;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
}
package com.srthinker.statinfo.api.kuangshi.api.device.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.device.DeviceApi;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.DeviceStatusResp;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.FirmwareBean;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import org.apache.commons.lang3.StringUtils;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class DeviceApiImpl implements DeviceApi {
private static final String STATUS_URL = "/api/devices/status";
private static final String FIRMWARE_URL = "/api/devices/firmware";
private static final String FIRMWARE_OTA_URL = "/api/devices/firmware/ota";
private DefaultApiClient httpClient;
public DeviceApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public DeviceStatusResp status() {
String resp = this.httpClient.doGet(STATUS_URL);
return JSONObject.parseObject(resp, DeviceStatusResp.class);
}
@Override
public FirmwareBean firmware(File file) {
BufferedInputStream bis = null;
try{
bis = new BufferedInputStream(new FileInputStream(file));
Map<String, InputStream> inputStreamMap = new HashMap<>();
inputStreamMap.put("file", bis);
String resp = this.httpClient.doPostFormMultipartByInputStream(FIRMWARE_URL, null, inputStreamMap);
return JSONObject.parseObject(resp, FirmwareBean.class);
} catch (Exception e) {
throw new RuntimeException("firmware error.");
} finally {
if(bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Override
public FirmwareBean firmwareOta(String otaUri, String md5) {
JSONObject paramJson = new JSONObject();
paramJson.put("ota_uri", otaUri);
/*if (!TextUtils.isEmpty(md5)){
paramJson.put("md5", md5);
}*/
if(StringUtils.isNotBlank(md5)) {
paramJson.put("md5", md5);
}
String resp = this.httpClient.doPostJson(FIRMWARE_OTA_URL, paramJson.toJSONString());
return JSONObject.parseObject(resp, FirmwareBean.class);
}
}
package com.srthinker.statinfo.api.kuangshi.api.group;
import com.srthinker.statinfo.api.kuangshi.api.group.bean.GroupBean;
import com.srthinker.statinfo.api.kuangshi.api.group.bean.GroupQueryIdResp;
/**
* 描述:人员组相关接口
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public interface GroupApi {
/**
* 添加人员组
* @param group
* @return
*/
GroupBean add(GroupBean group);
GroupQueryIdResp query(String group_id);
}
package com.srthinker.statinfo.api.kuangshi.api.group.bean;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 描述:人员组
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class GroupBean {
/**
* 客户端请求的id
*/
@JSONField(name = "request_id")
private String requestId;
/**
* 人员组的名称
*/
@JSONField(name = "group_name")
private String groupName;
/**
* 人员组绑定的门禁计划id
*/
@JSONField(name = "schedule_id")
private String scheduleId;
/**
* id
*/
@JSONField(name = "id")
private String id;
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getScheduleId() {
return scheduleId;
}
public void setScheduleId(String scheduleId) {
this.scheduleId = scheduleId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
package com.srthinker.statinfo.api.kuangshi.api.group.bean;
import java.util.List;
public class GroupQueryIdResp {
private String cmd;
private String id;
private String type;
private String group_name;
private int person_count;
private String create_timestamp;
private String schedule_id;
private List<LinksBean> links;
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getGroup_name() {
return group_name;
}
public void setGroup_name(String group_name) {
this.group_name = group_name;
}
public int getPerson_count() {
return person_count;
}
public void setPerson_count(int person_count) {
this.person_count = person_count;
}
public String getCreate_timestamp() {
return create_timestamp;
}
public void setCreate_timestamp(String create_timestamp) {
this.create_timestamp = create_timestamp;
}
public String getSchedule_id() {
return schedule_id;
}
public void setSchedule_id(String schedule_id) {
this.schedule_id = schedule_id;
}
public List<LinksBean> getLinks() {
return links;
}
public void setLinks(List<LinksBean> links) {
this.links = links;
}
public static class LinksBean {
private String rel;
private String href;
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
}
package com.srthinker.statinfo.api.kuangshi.api.group.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.group.GroupApi;
import com.srthinker.statinfo.api.kuangshi.api.group.bean.GroupBean;
import com.srthinker.statinfo.api.kuangshi.api.group.bean.GroupQueryIdResp;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import org.apache.commons.lang3.StringUtils;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class GroupApiImpl implements GroupApi {
private static final String POST_ITEM_URL = "/api/groups/item";
private static final String POST_QUERY_URL = "/api/groups/item";
private DefaultApiClient httpClient;
public GroupApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public GroupBean add(GroupBean group) {
String resp = this.httpClient.doPostJson(POST_ITEM_URL, JSONObject.toJSONString(group));
return JSONObject.parseObject(resp, GroupBean.class);
}
@Override
public GroupQueryIdResp query(String group_id) {
if (StringUtils.isEmpty(group_id)){
return null;
}else{
String resp = httpClient.doGet(POST_QUERY_URL + "/" + group_id);
//System.out.println(resp);
}
return null;
}
}
package com.srthinker.statinfo.api.kuangshi.api.pass;
import com.srthinker.statinfo.api.kuangshi.api.pass.bean.PassQueryBean;
public interface PassApi {
PassQueryBean query(int limit,int offset, String sort, String begin_time, String end_time);
//PassQueryBean query(String begin_time,String end_time);
}
package com.srthinker.statinfo.api.kuangshi.api.pass.bean;
public class Body {
private String sort;
private String begin_time;
private String end_time;
private int limit;
private int offset;
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public String getBegin_time() {
return begin_time;
}
public void setBegin_time(String begin_time) {
this.begin_time = begin_time;
}
public String getEnd_time() {
return end_time;
}
public void setEnd_time(String end_time) {
this.end_time = end_time;
}
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
/*public Body(int limit) {
this.limit = limit;
}*/
public Body(String sort, String begin_time, String end_time, int limit, int offset) {
this.sort = sort;
this.begin_time = begin_time;
this.end_time = end_time;
this.limit = limit;
this.offset = offset;
}
}
package com.srthinker.statinfo.api.kuangshi.api.pass.bean;
public class Paging {
private int limit;
private int offset;
private int total;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
package com.srthinker.statinfo.api.kuangshi.api.pass.bean;
import java.util.List;
public class PassQueryBean {
private String query_id;
private PagingBean paging;
private List<DataBean> data;
@Override
public String toString() {
return "PassQueryBean{" +
"query_id='" + query_id + '\'' +
", paging=" + paging +
", data=" + data +
'}';
}
public String getQuery_id() {
return query_id;
}
public void setQuery_id(String query_id) {
this.query_id = query_id;
}
public PagingBean getPaging() {
return paging;
}
public void setPaging(PagingBean paging) {
this.paging = paging;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class PagingBean {
private int limit;
private int offset;
private int total;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
public static class DataBean {
private String person_id;
private String person_code;
private String pass_mode;
private String verification_mode;
private String recognition_type;
private double recognition_score;
private boolean liveness;
private double liveness_score;
private String person_name;
private String card_number;
private String id_number;
private String timestamp;
private boolean mask;
private boolean therm;
private int temperature;
private int health_code;
public String getPerson_id() {
return person_id;
}
public void setPerson_id(String person_id) {
this.person_id = person_id;
}
public String getPerson_code() {
return person_code;
}
public void setPerson_code(String person_code) {
this.person_code = person_code;
}
public String getPass_mode() {
return pass_mode;
}
public void setPass_mode(String pass_mode) {
this.pass_mode = pass_mode;
}
public String getVerification_mode() {
return verification_mode;
}
public void setVerification_mode(String verification_mode) {
this.verification_mode = verification_mode;
}
public String getRecognition_type() {
return recognition_type;
}
public void setRecognition_type(String recognition_type) {
this.recognition_type = recognition_type;
}
public double getRecognition_score() {
return recognition_score;
}
public void setRecognition_score(double recognition_score) {
this.recognition_score = recognition_score;
}
public boolean isLiveness() {
return liveness;
}
public void setLiveness(boolean liveness) {
this.liveness = liveness;
}
public double getLiveness_score() {
return liveness_score;
}
public void setLiveness_score(double liveness_score) {
this.liveness_score = liveness_score;
}
public String getPerson_name() {
return person_name;
}
public void setPerson_name(String person_name) {
this.person_name = person_name;
}
public String getCard_number() {
return card_number;
}
public void setCard_number(String card_number) {
this.card_number = card_number;
}
public String getId_number() {
return id_number;
}
public void setId_number(String id_number) {
this.id_number = id_number;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public boolean isMask() {
return mask;
}
public void setMask(boolean mask) {
this.mask = mask;
}
public boolean isTherm() {
return therm;
}
public void setTherm(boolean therm) {
this.therm = therm;
}
public int getTemperature() {
return temperature;
}
public void setTemperature(int temperature) {
this.temperature = temperature;
}
public int getHealth_code() {
return health_code;
}
public void setHealth_code(int health_code) {
this.health_code = health_code;
}
}
}
package com.srthinker.statinfo.api.kuangshi.api.pass.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.pass.PassApi;
import com.srthinker.statinfo.api.kuangshi.api.pass.bean.Body;
import com.srthinker.statinfo.api.kuangshi.api.pass.bean.PassQueryBean;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
public class PassApiImpl implements PassApi {
private static final String PASS_QUERY_URL = "/api/passes/query";
private DefaultApiClient httpClient;
public PassApiImpl(DefaultApiClient httpClient){
this.httpClient = httpClient;
}
@Override
public PassQueryBean query(int limit,int offset,String sort, String begin_time, String end_time) {
String resp = httpClient.doPostJson(PASS_QUERY_URL, JSONObject.toJSONString(new Body(sort,begin_time,end_time,limit,offset)));
PassQueryBean passQueryBean = JSONObject.parseObject(resp, PassQueryBean.class);
return passQueryBean;
}
}
package com.srthinker.statinfo.api.kuangshi.api.person;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonBean;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonQueryResp;
/**
* 描述:人员类相关接口
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public interface PersonApi {
/**
* 添加人员
* @param person
*/
void add(PersonBean person);
PersonQueryResp query(int limit,int offset,String sort);
}
package com.srthinker.statinfo.api.kuangshi.api.person.bean;
/**
* 描述:人员照片
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class FaceListItem {
/**
* 照片索引
*/
private int idx;
/**
* Data URI: Base64编码的照片数据
*/
private String data;
public FaceListItem() {}
public FaceListItem(int idx, String data) {
this.idx = idx;
this.data = data;
}
public int getIdx() {
return idx;
}
public void setIdx(int idx) {
this.idx = idx;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
package com.srthinker.statinfo.api.kuangshi.api.person.bean;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* 描述:人员信息
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class PersonBean {
/**
* 人员id,为空时使用默认编号
*/
private String id;
/**
* 人员类型,staff – 普通人员,visitor – 访客,blacklist – 黑名单
*/
@JSONField(name = "recognition_type")
private String recognitionType;
/**
* 是否启用管理员权限
*/
@JSONField(name = "is_admin")
private String isAdmin;
/**
* 人员名称
*/
@JSONField(name = "person_name")
private String personName;
/**
* 密码加密方式,plain-明文, aes-AES加密
*/
@JSONField(name = "password_encrypt_type")
private String passwordEncryptType;
/**
* 密码使用6位数字
*/
@JSONField(name = "password")
private String password;
/**
* 卡号,最大20位数字
*/
@JSONField(name = "card_number")
private String cardNumber;
/**
* 绑定人员组的列表
*/
@JSONField(name = "group_list")
private List<String> groupList;
/**
* 人员照片
*/
@JSONField(name = "face_list")
private List<FaceListItem> faceList;
/**
* 人员编号
*/
@JSONField(name = "person_code")
private String personCode;
/**
* 身份证号码,需要aes加密!
*/
@JSONField(name = "id_number")
private String idNumber;
/**
* 访客开始时间,ISO8601格式,仅访客模式有效
*/
@JSONField(name = "visit_begin_time")
private String visitBeginTime;
/**
* 访客结束时间,ISO8601格式,仅访客模式有效
*/
@JSONField(name = "visit_end_time")
private String visitEndTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getRecognitionType() {
return recognitionType;
}
public void setRecognitionType(String recognitionType) {
this.recognitionType = recognitionType;
}
public String getIsAdmin() {
return isAdmin;
}
public void setIsAdmin(String isAdmin) {
this.isAdmin = isAdmin;
}
public String getPersonName() {
return personName;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public String getPasswordEncryptType() {
return passwordEncryptType;
}
public void setPasswordEncryptType(String passwordEncryptType) {
this.passwordEncryptType = passwordEncryptType;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
public List<String> getGroupList() {
return groupList;
}
public void setGroupList(List<String> groupList) {
this.groupList = groupList;
}
public List<FaceListItem> getFaceList() {
return faceList;
}
public void setFaceList(List<FaceListItem> faceList) {
this.faceList = faceList;
}
public String getPersonCode() {
return personCode;
}
public void setPersonCode(String personCode) {
this.personCode = personCode;
}
public String getVisitBeginTime() {
return visitBeginTime;
}
public void setVisitBeginTime(String visitBeginTime) {
this.visitBeginTime = visitBeginTime;
}
public String getVisitEndTime() {
return visitEndTime;
}
public void setVisitEndTime(String visitEndTime) {
this.visitEndTime = visitEndTime;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
}
package com.srthinker.statinfo.api.kuangshi.api.person.bean;
import java.util.List;
public class PersonQueryResp {
private String query_id;
private PagingBean paging;
private List<DataBean> data;
public String getQuery_id() {
return query_id;
}
public void setQuery_id(String query_id) {
this.query_id = query_id;
}
public PagingBean getPaging() {
return paging;
}
public void setPaging(PagingBean paging) {
this.paging = paging;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class PagingBean {
private int limit;
private int offset;
private int total;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
}
public static class DataBean {
private String recognition_type;
private String id;
private String type;
private boolean is_admin;
private String person_name;
private String card_number;
private String person_code;
private String id_number;
private List<String> group_list;
private List<LinksBean> links;
public String getRecognition_type() {
return recognition_type;
}
public void setRecognition_type(String recognition_type) {
this.recognition_type = recognition_type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isIs_admin() {
return is_admin;
}
public void setIs_admin(boolean is_admin) {
this.is_admin = is_admin;
}
public String getPerson_name() {
return person_name;
}
public void setPerson_name(String person_name) {
this.person_name = person_name;
}
public String getCard_number() {
return card_number;
}
public void setCard_number(String card_number) {
this.card_number = card_number;
}
public String getPerson_code() {
return person_code;
}
public void setPerson_code(String person_code) {
this.person_code = person_code;
}
public String getId_number() {
return id_number;
}
public void setId_number(String id_number) {
this.id_number = id_number;
}
public List<String> getGroup_list() {
return group_list;
}
public void setGroup_list(List<String> group_list) {
this.group_list = group_list;
}
public List<LinksBean> getLinks() {
return links;
}
public void setLinks(List<LinksBean> links) {
this.links = links;
}
public static class LinksBean {
private String rel;
private String href;
public String getRel() {
return rel;
}
public void setRel(String rel) {
this.rel = rel;
}
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
}
}
package com.srthinker.statinfo.api.kuangshi.api.person.bean;
public class QueryBody {
private int limit;
private int offset;
private String sort;
public int getLimit() {
return limit;
}
public void setLimit(int limit) {
this.limit = limit;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public String getSort() {
return sort;
}
public void setSort(String sort) {
this.sort = sort;
}
public QueryBody(int limit, int offset, String sort) {
this.limit = limit;
this.offset = offset;
this.sort = sort;
}
}
package com.srthinker.statinfo.api.kuangshi.api.person.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.person.PersonApi;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonBean;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonQueryResp;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.QueryBody;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class PersonApiImpl implements PersonApi {
private static final String POST_ITEM_URL = "/api/persons/item";
private static final String POST_QUERY_PERSON_URL = "/api/persons/query";
private DefaultApiClient httpClient;
public PersonApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public void add(PersonBean person) {
String resp = httpClient.doPostJson(POST_ITEM_URL, JSONObject.toJSONString(person));
System.out.println(resp);
}
@Override
public PersonQueryResp query(int limit, int offset, String sort) {
QueryBody queryBody = new QueryBody(limit, offset, sort);
String resp = httpClient.doPostJson(POST_QUERY_PERSON_URL, JSONObject.toJSONString(queryBody));
//System.out.println(resp);
PersonQueryResp personQueryResp = JSONObject.parseObject(resp, PersonQueryResp.class);
return personQueryResp;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleJsonBean;
/**
* 描述:门禁计划类接口
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public interface ScheduleApi {
/**
* 通过json数据格式添加
* @param item
* @return
*/
ScheduleJsonBean addScheduleItemByJson(ScheduleJsonBean item);
/**
* 通过crond数据格式添加
* @param item
* @return
*/
ScheduleCrondBean addScheduleItemByCrond(ScheduleCrondBean item);
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleBean {
/**
* 客户端请求的uuid【非必须】
*/
@JSONField(name = "request_id")
private String requestId;
/**
* 门禁计划的名称【必须】
*/
@JSONField(name = "schedule_name")
private String scheduleName;
/**
* 门禁计划的名称【非必须】
*/
@JSONField(name = "id")
private String id;
public String getRequestId() {
return requestId;
}
public void setRequestId(String requestId) {
this.requestId = requestId;
}
public String getScheduleName() {
return scheduleName;
}
public void setScheduleName(String scheduleName) {
this.scheduleName = scheduleName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleCrondBean extends ScheduleBean {
/**
* 门禁计划规则类型,crond-Linux定时计划格式,json-json计划格式。【非必须】
*/
@JSONField(name = "schedule_list_type")
private String scheduleListType = "crond";
/**
* 门禁计划时间列表【必须】
*/
@JSONField(name = "schedule_list")
private List<ScheduleListRuleCrondBean> scheduleList;
public List<ScheduleListRuleCrondBean> getScheduleList() {
return scheduleList;
}
public void setScheduleList(List<ScheduleListRuleCrondBean> scheduleList) {
this.scheduleList = scheduleList;
}
public String getScheduleListType() {
return scheduleListType;
}
public void setScheduleListType(String scheduleListType) {
this.scheduleListType = scheduleListType;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.List;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleJsonBean extends ScheduleBean {
/**
* 门禁计划规则类型,crond-Linux定时计划格式,json-json计划格式。【非必须】
*/
@JSONField(name = "schedule_list_type")
private String scheduleListType = "json";
/**
* 门禁计划时间列表【必须】
*/
@JSONField(name = "schedule_list")
private List<ScheduleListRuleJsonBean> scheduleList;
public List<ScheduleListRuleJsonBean> getScheduleList() {
return scheduleList;
}
public void setScheduleList(List<ScheduleListRuleJsonBean> scheduleList) {
this.scheduleList = scheduleList;
}
public String getScheduleListType() {
return scheduleListType;
}
public void setScheduleListType(String scheduleListType) {
this.scheduleListType = scheduleListType;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
/**
* 描述:门禁计划列表规则
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleListRuleBean {
/**
* 计划类型,workday 工作日,holiday 假日
*/
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleListRuleCrondBean extends ScheduleListRuleBean {
private String rule;
public String getRule() {
return rule;
}
public void setRule(String rule) {
this.rule = rule;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.bean;
import java.util.HashMap;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleListRuleJsonBean extends ScheduleListRuleBean {
private HashMap<String, String> rule = new HashMap<>();
public HashMap<String, String> getRule() {
return rule;
}
public void setRule(HashMap<String, String> rule) {
this.rule = rule;
}
}
package com.srthinker.statinfo.api.kuangshi.api.schedule.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.schedule.ScheduleApi;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleJsonBean;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
/**
* 描述:门禁计划相关接口
*
* @author: liuqingliang
* Date: 2021/3/9
*/
public class ScheduleApiImpl implements ScheduleApi {
private static final String POST_ITEM_URL = "/api/schedules/item";
private DefaultApiClient httpClient;
public ScheduleApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public ScheduleJsonBean addScheduleItemByJson(ScheduleJsonBean item) {
String resp = this.httpClient.doPostJson(POST_ITEM_URL, JSONObject.toJSONString(item));
return JSONObject.parseObject(resp, ScheduleJsonBean.class);
}
@Override
public ScheduleCrondBean addScheduleItemByCrond(ScheduleCrondBean item) {
String resp = this.httpClient.doPostJson(POST_ITEM_URL, JSONObject.toJSONString(item));
return JSONObject.parseObject(resp, ScheduleCrondBean.class);
}
}
package com.srthinker.statinfo.api.kuangshi.api.subscribe;
/**
* 描述:实时数据推送相关接口
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public interface SubscribeApi {
/**
* 设置第三方服务器推送配置
* @param serverUri 需要接收设备推送数据的uri
* @param enabled 是否启用
* @param method HTTP方法(serverUri对应的http请求对应的方法)
*/
void push(String serverUri, boolean enabled, String method);
}
package com.srthinker.statinfo.api.kuangshi.api.subscribe.impl;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.subscribe.SubscribeApi;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class SubscribeApiImpl implements SubscribeApi {
private static final String PUSH_URL = "/api/subscribe/push";
private DefaultApiClient httpClient;
public SubscribeApiImpl(DefaultApiClient httpClient) {
this.httpClient = httpClient;
}
@Override
public void push(String serverUri, boolean enabled, String method) {
JSONObject paramJson = new JSONObject();
paramJson.put("server_uri", serverUri);
paramJson.put("enabled", enabled);
paramJson.put("method", method);
this.httpClient.doPutJson(PUSH_URL, paramJson.toJSONString());
}
}
package com.srthinker.statinfo.api.kuangshi.client;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/10
*/
public class ApiClientException extends RuntimeException {
private int httpStatus;
private String message;
private String response;
public ApiClientException() {
}
public ApiClientException(int httpStatus, String message, String response) {
this.httpStatus = httpStatus;
this.message = message;
this.response = response;
}
public int getHttpStatus() {
return httpStatus;
}
public void setHttpStatus(int httpStatus) {
this.httpStatus = httpStatus;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
package com.srthinker.statinfo.api.kuangshi.client;
import com.srthinker.statinfo.api.kuangshi.utils.http.okhttp.IProgress;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
public class DefaultApiClient {
private static Logger log = LoggerFactory.getLogger(DefaultApiClient.class);
private static final int UPLOAD_BUFFER_SIZE =4096;
private static final int M1 = 1024 * 1024;
private static final String EMPTY_JSON = "{}";
private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");
private OkHttpClient okHttpClient;
private String apiServerHttpUrlPrefix;
private static Set<Integer> SKIP_VALID_CODES = new HashSet<>();
static {
SKIP_VALID_CODES.add(200);
SKIP_VALID_CODES.add(201);
SKIP_VALID_CODES.add(202);
SKIP_VALID_CODES.add(401);
}
/**
* cookie
*/
private String coolie;
public DefaultApiClient(String apiServerHttpUrlPrefix) {
this(apiServerHttpUrlPrefix, 15, 900, 900);
}
public DefaultApiClient(String apiServerHttpUrlPrefix, int connectTimeoutSeconds, int writeTimeoutSeconds, int readTimeoutSeconds) {
if(apiServerHttpUrlPrefix.endsWith("/")) {
apiServerHttpUrlPrefix = apiServerHttpUrlPrefix.substring(0, apiServerHttpUrlPrefix.length() - 1);
}
this.apiServerHttpUrlPrefix = apiServerHttpUrlPrefix;
okHttpClient = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
//10s连接超时
.connectTimeout(connectTimeoutSeconds, TimeUnit.SECONDS)
//写入超时
.writeTimeout(writeTimeoutSeconds, TimeUnit.SECONDS)
//读取超时
.readTimeout(readTimeoutSeconds, TimeUnit.SECONDS)
.build();
}
//---------------------------- http get methods
public String doGet(String url) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForGet(url, null);
return commonRequest(request);
}
public String doGet(String url, Map<String, String> params) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForGet(url, params);
return commonRequest(request);
}
//---------------------------- http post methods
public String doPostJson(String url, String json) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForPostJson(url, json);
return commonRequest(request);
}
public String doPostForm(String url, Map<String, String> params) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForPostForm(url, params);
return commonRequest(request);
}
public String doPostFormMultipartByInputStream(String url, Map<String, String> params, Map<String, InputStream> files) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForPostFormMultipartByInputStream(url, params, files);
return commonRequest(request);
}
//----------------------http delete
public String doDeleteJson(String url, String json) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForDeleteJson(url, json);
return commonRequest(request);
}
//----------------------http put
public String doPutJson(String url, String json) {
if (isBlankUrl(url)) {
return null;
}
Request request = getRequestForPutJson(url, json);
return commonRequest(request);
}
//----------------------private method
//----------------------create request
private Request getRequestForPostJson(String url, String json) {
log.info("url={}, body={}", url, json);
RequestBody body = createRequestJsonBody(json);
Request request = createBuilder(url)
.post(body)
.build();
return request;
}
private Request getRequestForPostForm(String url, Map<String, String> params) {
if (params == null) {
params = new HashMap<>();
}
FormBody.Builder builder = new FormBody.Builder();
if (params != null && params.size() > 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.addEncoded(entry.getKey(), entry.getValue());
}
}
RequestBody requestBody = builder.build();
Request request = createBuilder(url)
.post(requestBody)
.build();
return request;
}
private Request getRequestForDeleteJson(String url, String json) {
RequestBody body = createRequestJsonBody(json);
Request request = createBuilder(url)
.delete(body)
.build();
return request;
}
private Request getRequestForPutJson(String url, String json) {
RequestBody body = createRequestJsonBody(json);
Request request = createBuilder(url)
.put(body)
.build();
return request;
}
private Request getRequestForPostFormMultipartByInputStream(String url, Map<String, String> params, Map<String, InputStream> files) {
MultipartBody.Builder builder = new MultipartBody.Builder();
if (params != null && params.size() > 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.addFormDataPart(entry.getKey(), entry.getValue());
}
}
if (files != null && files.size() > 0) {
for (Map.Entry<String, InputStream> entry : files.entrySet()) {
builder.addFormDataPart(entry.getKey(), entry.getKey(), createCustomRequestBody(MediaType.parse("image"),
entry.getValue(), -1,
(totalBytes, handledCounnt) ->
log.debug("文件已上传:{}B", handledCounnt)
));
}
}
builder.setType(MediaType.parse("multipart/form-data"));
RequestBody requestBody = builder.build();
Request request = createBuilder(url)
.post(requestBody)
.addHeader("Content-Type", "multipart/form-data")
.header("Connection", "close")
.header("Accept-Encoding", "identity")
.build();
return request;
}
public RequestBody createCustomRequestBody(final MediaType contentType, InputStream inputStream, long contentLength, final IProgress listener) {
return new RequestBody() {
@Override
public MediaType contentType() {
return contentType;
}
@Override
public long contentLength() {
return contentLength;
}
@Override
public void writeTo(BufferedSink sink) {
Source source;
try {
source = Okio.source(new BufferedInputStream(inputStream));
Buffer buf = new Buffer();
long handledCount = 0;
for (long readCount; (readCount = source.read(buf, UPLOAD_BUFFER_SIZE)) != -1; ) {
sink.write(buf, readCount);
handledCount += readCount;
if(handledCount % M1 == 0) {
listener.onProgress(contentLength(), handledCount);
} else if(contentLength == handledCount) {
//如果都读取完了
listener.onProgress(contentLength(), handledCount);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
private Request getRequestForGet(String url, Map<String, String> params) {
Request request = createBuilder(getUrlStringForGet(url, params))
.build();
return request;
}
private String getUrlStringForGet(String url, Map<String, String> params) {
if(params == null || params.isEmpty()) {
return url;
}
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(url);
urlBuilder.append("?");
if (params != null && params.size() > 0) {
for (Map.Entry<String, String> entry : params.entrySet()) {
try {
urlBuilder.append("&").append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
} catch (Exception e) {
urlBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
}
}
return urlBuilder.toString();
}
//--------------request execute
private String commonRequest(Request request) {
String re = "";
try {
Call call = okHttpClient.newCall(request);
Response response = call.execute();
if (SKIP_VALID_CODES.contains(response.code())) {
re = response.body().string();
log.info("request url:{};response:{}", request.url().toString(), re);
} else {
re = response.body().string();
log.info("request failure url:{}; status:{}, message:{}, response:{}", request.url().toString(), response.code(), response.message(), re);
throw new ApiClientException(response.code(), response.message(), re);
}
} catch (ApiClientException e2) {
e2.printStackTrace();
log.error("ApiClientException", e2);
throw e2;
} catch (Exception e) {
e.printStackTrace();
log.error("request execute failure", e);
throw new RuntimeException("http error");
}
return re;
}
//-------------- tool methods
private Boolean isBlankUrl(String url) {
if (StringUtils.isBlank(url)) {
log.info("url is not blank");
return true;
} else {
return false;
}
}
private RequestBody createRequestJsonBody(String json) {
if(StringUtils.isBlank(json)) {
json = EMPTY_JSON;
}
RequestBody body = RequestBody.create(MEDIA_TYPE_JSON, json);
return body;
}
//-------------- getter and setter
public void setCoolie(String coolie) {
this.coolie = coolie;
}
private Request.Builder createBuilder(String url) {
Request.Builder builder = new Request.Builder();
if(!StringUtils.isAllBlank(coolie)) {
builder.addHeader("Cookie", coolie);
}
if(!url.startsWith("/")) {
url = "/" + url;
}
builder.url(apiServerHttpUrlPrefix + url);
return builder;
}
}
package com.srthinker.statinfo.api.kuangshi.utils;
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* 描述:TODO
*
* @author: liuqingliang
* Date: 2021/3/1
*/
public class DigestUtils {
/**
* 加密算法
*/
private static final String KEY_ALGORITHM = "AES";
/**
* 设定秘钥长度
*/
private static final int KEY_LENGTH = 32;
//AES_256_cbc pkcs7
private static final String ALGORITHM = "AES/ECB/PKCS7Padding";
/**
* 用来补位
*/
static StringBuffer additionalStr = new StringBuffer("00000000000000000000000000000000");
/**
* ASE加密
* @param data
* @param secretKey
* @return
*/
public static String aesEncrypt(String data, String secretKey) {
try {
SecretKeySpec keySpec = getSecretKey(secretKey);
//Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
//return Base64.getEncoder().encodeToString(encData);
return android.util.Base64.encodeToString(encData,android.util.Base64.DEFAULT);
} catch (Exception e) {
throw new RuntimeException("aes encrypt error.");
}
}
public static String aesDecrypt(String base64Data, String secretKey) {
try {
SecretKeySpec keySpec = getSecretKey(secretKey);
//Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, keySpec);
//byte[] decbbdt = cipher.doFinal(Base64.getDecoder().decode(base64Data));
byte[] decbbdt = cipher.doFinal(android.util.Base64.decode(base64Data,android.util.Base64.DEFAULT));
return new String(decbbdt, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException("aes decrypt error.");
}
}
public static String sha256(String value){
MessageDigest sha = null;
try {
sha = MessageDigest.getInstance("SHA-256");
byte[] byteArray = value.getBytes("UTF-8");
byte[] md5Bytes = sha.digest(byteArray);
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));
}
return hexValue.toString();
} catch (Exception e) {
throw new RuntimeException("sha256 error");
}
}
/**
* 使用密码获取 AES 秘钥
*/
public static SecretKeySpec getSecretKey(String key) {
if (StringUtils.isEmpty(key)) {
return null;
}
try {
if (key.length() > KEY_LENGTH) {
key = key.substring(0, KEY_LENGTH);
} else if (key.length() < KEY_LENGTH) {
int count = KEY_LENGTH - key.length();
String addstr = additionalStr.substring(0, count);
key = key + addstr;
}
return new SecretKeySpec(key.getBytes(), KEY_ALGORITHM);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.srthinker.statinfo.api.kuangshi.utils.http.okhttp;
/**
* 描述:进度回调接口
* Author: zhouxi
* Date: 2020/3/11
*/
public interface IProgress {
/**
* 进度条回调
* @param handledBytes 已处理完的字节数组
*/
void onProgress(long totalBytes, long handledBytes);
}
package com.srthinker.statinfo.bean;
import java.util.Objects;
public class ConfigBean {
private String username;
private String password;
private String serverIp;
private boolean isConnect;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
public boolean isConnect() {
return isConnect;
}
public void setConnect(boolean connect) {
isConnect = connect;
}
public ConfigBean() {
}
public ConfigBean(String username, String password, String serverIp, boolean isConnect) {
this.username = username;
this.password = password;
this.serverIp = serverIp;
this.isConnect = isConnect;
}
public ConfigBean(String username, String password, String serverIp) {
this.username = username;
this.password = password;
this.serverIp = serverIp;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConfigBean that = (ConfigBean) o;
return isConnect == that.isConnect && Objects.equals(username, that.username) && Objects.equals(password, that.password) && Objects.equals(serverIp, that.serverIp);
}
@Override
public int hashCode() {
return Objects.hash(username, password, serverIp, isConnect);
}
@Override
public String toString() {
return "ConfigBean{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", serverIp='" + serverIp + '\'' +
", isConnect=" + isConnect +
'}';
}
}
package com.srthinker.statinfo.bean;
public class GroupBean {
private String desc;
private int number;
private int color;
private String type;
public GroupBean(String desc, int number, int color, String type) {
this.desc = desc;
this.number = number;
this.color = color;
this.type = type;
}
public GroupBean() {
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
package com.srthinker.statinfo.bean;
public class PeopleBean {
private String time;
private String name;
private int type; //进出情况:进:0,出:1
public PeopleBean() {
}
public PeopleBean(String time, String name) {
this.time = time;
this.name = name;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
package com.srthinker.statinfo.bean;
public class PointBean {
private String time;
private int people_num;
private int type;
public PointBean() {
}
public PointBean(String time, int people_num, int type) {
this.time = time;
this.people_num = people_num;
this.type = type;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public int getPeople_num() {
return people_num;
}
public void setPeople_num(int people_num) {
this.people_num = people_num;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
package com.srthinker.statinfo.bean;
public class TimeBean {
private String yMD;
private String hm;
private String week;
public TimeBean(String yMD, String hm, String week) {
this.yMD = yMD;
this.hm = hm;
this.week = week;
}
public TimeBean() {
}
public String getyMD() {
return yMD;
}
public void setyMD(String yMD) {
this.yMD = yMD;
}
public String getHm() {
return hm;
}
public void setHm(String hm) {
this.hm = hm;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
}
package com.srthinker.statinfo.constant;
public class Const {
public static final String DEVICE_TYPE = "RC13";
}
package com.srthinker.statinfo.constant;
public class GroupConst {
public static final String WATERPROOF = "waterproof";
public static final String OUTRIGGER = "outrigger";
public static final String BUILD = "build";
public static final String SUPERVISOR = "supervisor";
public static final int WATERPROOF_ID = 1;
public static final int OUTRIGGER_ID = 2;
public static final int BUILD_ID = 3;
public static final int SUPERVISOR_ID = 4;
public static final int NO_GROUP = 100;
public static final int GROUPED = 200;
}
package com.srthinker.statinfo.constant;
public class InOutType {
public static final int ENTER_TYPE = 0x12138;
public static final int LEAVE_TYPE = 0x22138;
}
package com.srthinker.statinfo.database;
import com.raizlabs.android.dbflow.annotation.Database;
@Database(name = AppDB.DB_NAME,version = AppDB.DB_VERSION)
public class AppDB {
public static final String DB_NAME = "AppDB";
public static final int DB_VERSION = 1;
}
package com.srthinker.statinfo.database;
import android.text.TextUtils;
import android.util.Log;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.helper.PersonHelper;
import com.srthinker.statinfo.listener.PersonMgrCallback;
import com.srthinker.statinfo.util.common.ThreadPool;
import java.util.ArrayList;
import java.util.List;
public class PersonMgr {
private static final String TAG = "PersonMgr";
private static PersonMgr personMgr;
private final PersonHelper personHelper;
// private PersonMgrCallback callback;
private PersonMgr(){
personHelper = new PersonHelper();
}
public static PersonMgr getInstance(){
if (personMgr == null) {
synchronized (PersonMgr.class){
personMgr = new PersonMgr();
}
}
return personMgr;
}
/* public void setOnPersonMgrCallback(PersonMgrCallback callback){
this.callback = callback;
}*/
//从接口中拿去新数据
private void updatePerson(List<PersonEntity> personEntities){
List<PersonEntity> queryPersons = personHelper.queryAll();
Log.i(TAG, "updatePerson: queryPersons="+queryPersons.size());
//如果拉来的数据为空或者为null
if (personEntities==null || personEntities.size()<=0){
return;
}
//如果数据库为空或没有
if (queryPersons==null||queryPersons.size()<=0){
personHelper.add(personEntities);
return;
}
//如果都有
//给从接口获取新的数据之前有分过组的数据写分组的信息,已经被删除的人员也要删除掉
ArrayList<PersonEntity> needDelPersons = new ArrayList<>();
for (PersonEntity queryPerson : queryPersons) {
String queryId = queryPerson.getId();
boolean isFound = false;
for (PersonEntity newPersonEntity : personEntities) {
String newId = newPersonEntity.getId();
if (TextUtils.equals(queryId,newId)){
newPersonEntity.setGroup(queryPerson.getGroup());
isFound = true;
break;
}
}
if (!isFound){
needDelPersons.add(queryPerson);
}
}
if (personHelper != null) {
personHelper.save(personEntities);
Log.i(TAG, "updatePerson: needDelPersons.size()="+needDelPersons.size());
personHelper.delete(needDelPersons);
}
}
public void updatePersonThread(List<PersonEntity> personEntities,PersonMgrCallback callback){
ThreadPool.getInstance().getThreadPoolExecutor().execute(new Runnable() {
@Override
public void run() {
updatePerson(personEntities);
if (callback != null) {
callback.personUpdated();
}
}
});
}
/* public void getUpdatePerson(List<PersonEntity> personEntities){
Runnable updatePersonRunnable = () -> {
List<PersonEntity> updatePersonList = new ArrayList<>();
updatePerson(personEntities);
updatePersonList = personHelper.queryAll();
if (callback != null) {
callback.getUpdatePerson(updatePersonList);
}
};
ThreadPool.getInstance().getThreadPoolExecutor().execute(updatePersonRunnable);
}*/
//从组列表中获取有分组的列表(获取的列表不一定是全部的,可能是部分的
private void updateFromList(List<PersonEntity> personEntities){
// Log.i(TAG, "updateFromList: personEntities.size="+personEntities.size());
List<PersonEntity> queryPersons = personHelper.queryAll();
// Log.i(TAG, "updateFromList: queryPersons.size="+queryPersons.size());
if (personEntities==null || personEntities.size()<=0){
return ;
}
if (queryPersons==null || queryPersons.size()<=0){
return ;
}
List<PersonEntity> needUpdate = new ArrayList<>();
for (PersonEntity personEntity : personEntities) {
String personId = personEntity.getId();
for (PersonEntity queryPerson : queryPersons) {
String queryId = queryPerson.getId();
if (TextUtils.equals(personId,queryId)){
queryPerson.setGroup(personEntity.getGroup());
needUpdate.add(queryPerson);
break;
}
}
}
if (personHelper != null) {
personHelper.update(needUpdate);
}
}
public void updateFromListThread(List<PersonEntity> personEntities,PersonMgrCallback callback){
ThreadPool.getInstance().getThreadPoolExecutor().execute(new Runnable() {
@Override
public void run() {
updateFromList(personEntities);
if (callback != null) {
callback.personUpdated();
}
}
});
}
/*public void getUpdateFromList(List<PersonEntity> personEntities){
Runnable updateFromListRunnable = ()->{
List<PersonEntity> resultList = new ArrayList<>();
updateFromList(personEntities);
resultList = personHelper.queryAll();
if (callback != null) {
callback.getUpdatePerson(resultList);
}
};
ThreadPool.getInstance().getThreadPoolExecutor().execute(updateFromListRunnable);
}*/
}
package com.srthinker.statinfo.database.entity;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.srthinker.statinfo.database.AppDB;
import java.util.Objects;
@Table(database = AppDB.class)
public class ConfigEntity extends BaseModel {
@PrimaryKey(autoincrement = true)
@Column
private int id;
@Column
private String username;
@Column
private String password;
@Column
private String serverIp;
@Column
private boolean isConnect;
@Column
private int type; //是进设备还是出设备
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
public boolean isConnect() {
return isConnect;
}
public void setConnect(boolean connect) {
isConnect = connect;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ConfigEntity config = (ConfigEntity) o;
return id == config.id && isConnect == config.isConnect && type == config.type && Objects.equals(username, config.username) && Objects.equals(password, config.password) && Objects.equals(serverIp, config.serverIp);
}
@Override
public int hashCode() {
return Objects.hash(id, username, password, serverIp, isConnect, type);
}
}
package com.srthinker.statinfo.database.entity;
import com.raizlabs.android.dbflow.annotation.Column;
import com.raizlabs.android.dbflow.annotation.PrimaryKey;
import com.raizlabs.android.dbflow.annotation.Table;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.srthinker.statinfo.database.AppDB;
import java.util.Objects;
@Table(database = AppDB.class)
public class PersonEntity extends BaseModel {
@PrimaryKey
@Column
private String id;
@Column
private String type;
@Column
private String recognition_type;
@Column
private String person_name;
@Column
private String card_number;
@Column
private String person_code;
@Column
private String id_number;
@Column
private int group;
@Column
private String picture_data;
@Column
private String timestamp;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getRecognition_type() {
return recognition_type;
}
public void setRecognition_type(String recognition_type) {
this.recognition_type = recognition_type;
}
public String getPerson_name() {
return person_name;
}
public void setPerson_name(String person_name) {
this.person_name = person_name;
}
public String getCard_number() {
return card_number;
}
public void setCard_number(String card_number) {
this.card_number = card_number;
}
public String getPerson_code() {
return person_code;
}
public void setPerson_code(String person_code) {
this.person_code = person_code;
}
public String getId_number() {
return id_number;
}
public void setId_number(String id_number) {
this.id_number = id_number;
}
public int getGroup() {
return group;
}
public void setGroup(int group) {
this.group = group;
}
public String getPicture_data() {
return picture_data;
}
public void setPicture_data(String picture_data) {
this.picture_data = picture_data;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PersonEntity that = (PersonEntity) o;
return group == that.group && Objects.equals(id, that.id) && Objects.equals(type, that.type) && Objects.equals(recognition_type, that.recognition_type) && Objects.equals(person_name, that.person_name) && Objects.equals(card_number, that.card_number) && Objects.equals(person_code, that.person_code) && Objects.equals(id_number, that.id_number) && Objects.equals(picture_data, that.picture_data) && Objects.equals(timestamp, that.timestamp);
}
@Override
public int hashCode() {
return Objects.hash(id, type, recognition_type, person_name, card_number, person_code, id_number, group, picture_data, timestamp);
}
}
package com.srthinker.statinfo.database.helper;
import com.raizlabs.android.dbflow.config.DatabaseDefinition;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper;
import com.raizlabs.android.dbflow.structure.database.transaction.ITransaction;
import com.srthinker.statinfo.database.AppDB;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import com.srthinker.statinfo.database.entity.ConfigEntity_Table;
import com.srthinker.statinfo.util.common.Mutex;
import java.util.List;
public class ConfigHelper {
private static ConfigHelper configHelper;
private Mutex locker = new Mutex();
public static ConfigHelper getInstance(){
if (configHelper == null) {
synchronized (ConfigHelper.class){
configHelper = new ConfigHelper();
}
}
return configHelper;
}
public boolean save(ConfigEntity entity){
boolean result = false;
locker.lock(0);
result = entity.save();
locker.unlock();
return result;
}
public long add(ConfigEntity entity) {
long result = -1;
locker.lock(0);
result = entity.insert();
locker.unlock();
return result;
}
public void add(List<ConfigEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (ConfigEntity entity : entities) {
entity.insert(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public void save(List<ConfigEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (ConfigEntity entity : entities) {
entity.save(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public boolean delete(ConfigEntity entity) {
boolean result = false;
locker.lock(0);
result = entity.delete();
locker.unlock();
return result;
}
public void delete(List<ConfigEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (ConfigEntity entity : entities) {
entity.delete(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public void update(List<ConfigEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (ConfigEntity entity : entities) {
entity.update(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public boolean update(ConfigEntity entity) {
boolean result = false;
locker.lock(0);
result = entity.update();
locker.unlock();
return result;
}
public void clear() {
locker.lock(0);
SQLite.delete(ConfigEntity.class).execute();
locker.unlock();
}
public List<ConfigEntity> queryAll(){
List<ConfigEntity> configEntityList = null;
locker.lock(0);
configEntityList = SQLite.select().from(ConfigEntity.class).queryList();
locker.unlock();
return configEntityList;
}
public List<ConfigEntity> queryByType(int type){
List<ConfigEntity> configEntityList = null;
locker.lock(0);
configEntityList = SQLite.select().from(ConfigEntity.class).where(ConfigEntity_Table.type.eq(type)).queryList();
locker.unlock();
return configEntityList;
}
public List<ConfigEntity> queryByTypeIp(int type,String ip){
List<ConfigEntity> configEntityList = null;
locker.lock(0);
configEntityList = SQLite.select().from(ConfigEntity.class).where(ConfigEntity_Table.type.eq(type)).and(ConfigEntity_Table.serverIp.eq(ip)).queryList();
locker.unlock();
return configEntityList;
}
public ConfigEntity queryById(int id){
ConfigEntity entity = null;
locker.lock(0);
entity = SQLite.select().from(ConfigEntity.class).where(ConfigEntity_Table.id.eq(id)).querySingle();
locker.unlock();
return entity;
}
public ConfigEntity queryByIp(String ip){
ConfigEntity entity = null;
locker.lock(0);
entity = SQLite.select().from(ConfigEntity.class).where(ConfigEntity_Table.serverIp.eq(ip)).querySingle();
locker.unlock();
return entity;
}
}
package com.srthinker.statinfo.database.helper;
import com.raizlabs.android.dbflow.config.DatabaseDefinition;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper;
import com.raizlabs.android.dbflow.structure.database.transaction.ITransaction;
import com.srthinker.statinfo.database.AppDB;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.entity.PersonEntity_Table;
import com.srthinker.statinfo.util.common.Mutex;
import java.util.List;
public class PersonHelper {
private static PersonHelper mHelper = null;
private Mutex locker = new Mutex();
public static PersonHelper getInstance(){
if (mHelper == null) {
synchronized (PersonHelper.class){
mHelper = new PersonHelper();
}
}
return mHelper;
}
public boolean save(PersonEntity entity){
boolean result = false;
locker.lock(0);
result = entity.save();
locker.unlock();
return result;
}
public long add(PersonEntity entity) {
long result = -1;
locker.lock(0);
result = entity.insert();
locker.unlock();
return result;
}
public void add(List<PersonEntity> entities){
/*FlowManager.getDatabase(AppDB.class).executeTransaction(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
FastStoreModelTransaction<PersonEntity> fastStoreModelTransaction =
FastStoreModelTransaction.saveBuilder(FlowManager.getModelAdapter(PersonEntity.class))
.addAll(entities)
.build();
fastStoreModelTransaction.execute(databaseWrapper);
}
});*/
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (PersonEntity entity : entities) {
entity.insert(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public void save(List<PersonEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (PersonEntity entity : entities) {
entity.save(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public boolean delete(PersonEntity entity) {
boolean result = false;
locker.lock(0);
result = entity.delete();
locker.unlock();
return result;
}
public void delete(List<PersonEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (PersonEntity entity : entities) {
entity.delete(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public void update(List<PersonEntity> entities){
locker.lock(0);
DatabaseDefinition database = FlowManager.getDatabase(AppDB.class);
database.beginTransactionAsync(new ITransaction() {
@Override
public void execute(DatabaseWrapper databaseWrapper) {
for (PersonEntity entity : entities) {
entity.update(databaseWrapper);
}
}
}).build().execute();
locker.unlock();
}
public boolean update(PersonEntity entity) {
boolean result = false;
locker.lock(0);
result = entity.update();
locker.unlock();
return result;
}
public void clear() {
locker.lock(0);
SQLite.delete(PersonEntity.class).execute();
locker.unlock();
}
public List<PersonEntity> queryAll(){
List<PersonEntity> personEntityList = null;
locker.lock(0);
personEntityList = SQLite.select().from(PersonEntity.class).queryList();
locker.unlock();
return personEntityList;
}
public PersonEntity queryById(String id){
PersonEntity entity = null;
locker.lock(0);
entity = SQLite.select().from(PersonEntity.class).where(PersonEntity_Table.id.eq(id)).querySingle();
locker.unlock();
return entity;
}
public List<PersonEntity> queryByGroup(int group){
List<PersonEntity> personEntities = null;
locker.lock(0);
personEntities = SQLite.select().from(PersonEntity.class).where(PersonEntity_Table.group.eq(group)).queryList();
locker.unlock();
return personEntities;
}
}
package com.srthinker.statinfo.download;
import android.os.Environment;
/**
* @author liwanlian
* @date 2023/3/15 10:14
*/
public abstract class BaseDownloadImpl {
private static final String TAG = "lwl-DownloadImpl";
protected DownloadCallback downloadCallback;
public void setDownloadCallback(DownloadCallback downloadCallback) {
this.downloadCallback = downloadCallback;
}
/**
* 数据初始化
*/
protected abstract void initData();
/**
* 启动下载
*
* @param downloadUrl
* @param filePath
*/
public void startDownload(String downloadUrl, String filePath) {
}
public void startDownload(String downloadUrl, String filePath, long startPoint, long totalSize) {
}
/**
* 文件上传
*
* @param filePath
* @param uploadUrl
*/
public void uploadFile(String filePath, String uploadUrl) {
}
/**
* 资源释放
*/
public void releaseRes() {
}
public String getFilename(String path) {
int start = path.lastIndexOf("/") + 1;
String substring = path.substring(start);
String fileName = Environment.getExternalStorageDirectory().getPath() + "/" + substring;
return fileName;
}
}
package com.srthinker.statinfo.download;
public interface DownloadCallback {
/**
* 开始下载
*/
void onStart(String downloadUrl,String filePath);
/**
* 下载中
*/
void onProgress(long currentSize,long totalSize,String downloadUrl,String filePath);
/**
* 完成
* @param
*/
void onFinish(String downloadUrl,String filePath);
/**
* 出错
* @param error
*/
void onError(String error,String downloadUrl, String filePath);
}
package com.srthinker.statinfo.download;
import android.text.TextUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkhttpInterruptDownImpl extends BaseDownloadImpl{
private static OkhttpInterruptDownImpl down;
private FileOutputStream fos;
private InputStream inputStream;
private Call call;
private String TAG = "OkhttpInterruptDownImpl";
public static OkhttpInterruptDownImpl getInstance(){
if (down == null) {
synchronized (OkhttpInterruptDownImpl.class){
down = new OkhttpInterruptDownImpl();
}
}
return down;
}
@Override
protected void initData() {
}
@Override
public void startDownload(String downloadUrl, String filePath) {
super.startDownload(downloadUrl, filePath);
boolean isFinish = true;
long downloadedBytes = 0;
if (TextUtils.isEmpty(downloadUrl)){
if (downloadCallback!=null){
downloadCallback.onError("路径为空",downloadUrl,filePath);
return;
}
}
File downFile = new File(filePath);
if (downFile.exists()){
downloadedBytes = downFile.length();
}
try {
//OkHttpClient client = new OkHttpClient();
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS) // 设置连接超时时间为10秒
.readTimeout(60, TimeUnit.SECONDS) // 设置读取超时时间为10秒
.build();
Request request = new Request.Builder().url(downloadUrl)
.header("Range", "bytes=" + downloadedBytes + "-")
.build();
call = client.newCall(request);
Response response = call.execute();
if (response.isSuccessful()){
//从响应头获取要下载的大小
Long totalBytes = Long.parseLong(response.header("Content-Length"))+downloadedBytes; //Content-Length获取的不是总大小,而是看你从哪里读起
fos = new FileOutputStream(downFile, true);
//读取并写入
inputStream = response.body().byteStream();
//开始下载文件
byte[] bytes = new byte[2048];
int bytesRead;
long totalDownloadedBytes = downloadedBytes;
if (downloadCallback != null) {
downloadCallback.onStart(downloadUrl,filePath);
}
//Log.i(TAG, "saveRangeFile: totalDownloadedBytes="+ Formatter.formatFileSize(context,totalDownloadedBytes));
while ((bytesRead = inputStream.read(bytes))!=-1){
fos.write(bytes,0,bytesRead);
totalDownloadedBytes += bytesRead;
if (downloadCallback != null) {
downloadCallback.onProgress(totalDownloadedBytes,totalBytes,downloadUrl,filePath);
}
}
inputStream.close();
fos.close();
}else{
isFinish = false;
if (downloadCallback != null) {
downloadCallback.onError("响应码为:"+response.code(),downloadUrl,filePath);
}
}
} catch (Exception e) {
isFinish = false;
e.printStackTrace();
if (!TextUtils.equals(e.getMessage(),"Socket closed") && !TextUtils.equals(e.getMessage(),"Socket is closed")){
if(downloadCallback!=null){
//下载失败
downloadCallback.onError(e.toString(),downloadUrl,filePath);
}
}
}finally {
if (isFinish){
if (downloadCallback != null) {
downloadCallback.onFinish(downloadUrl,filePath);
}
}
}
}
@Override
public void startDownload(String downloadUrl, String filePath, long startPoint, long totalSize) {
super.startDownload(downloadUrl, filePath, startPoint, totalSize);
}
@Override
public void releaseRes() {
super.releaseRes();
try {
/*if (fos != null) {
fos.close();
}
if (inputStream != null) {
inputStream.close();
}*/
call.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopDownload(){
releaseRes();
}
}
package com.srthinker.statinfo.download.upper;
public class DownStatus {
public final static int DOWN_FINISH = 1;
public final static int DOWN_ERROR = 2;
public final static int DOWN_START = 3;
}
package com.srthinker.statinfo.download.upper;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_ERROR;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_FINISH;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_START;
import android.app.Activity;
import androidx.lifecycle.ViewModel;
import com.srthinker.statinfo.download.DownloadCallback;
import com.srthinker.statinfo.download.OkhttpInterruptDownImpl;
import com.srthinker.statinfo.util.common.ThreadPool;
public class DownloadViewModel extends ViewModel implements DownloadCallback {
private final Activity activity;
private OkhttpInterruptDownImpl okhttpInterruptDown;
private UpperDownloadCallback upperDownloadCallback;
private float lastProgress=-1.0f;
public DownloadViewModel(Activity activity){
this.activity = activity;
}
public void initData(){
okhttpInterruptDown = new OkhttpInterruptDownImpl();
okhttpInterruptDown.setDownloadCallback(this);
}
public void setOnUpperDownloadCallback(UpperDownloadCallback upperDownloadCallback){
this.upperDownloadCallback = upperDownloadCallback;
}
public void startDownload(String downloadUrl,String filePath){
Runnable runnable = new Runnable() {
@Override
public void run() {
okhttpInterruptDown.startDownload(downloadUrl,filePath);
}
};
ThreadPool.getInstance().getThreadPoolExecutor().execute(runnable);
}
public void stopDownload(){
okhttpInterruptDown.stopDownload();
}
@Override
public void onProgress(long currentSize, long totalSize, String downloadUrl, String filePath) {
if (upperDownloadCallback != null) {
int progress = (int) ((currentSize * 1.0 / totalSize)*100);
if (progress!=lastProgress){
String progressString = progress + "%";
upperDownloadCallback.onProgress(progressString,filePath);
lastProgress = progress;
}
}
}
@Override
public void onStart(String downloadUrl, String filePath) {
if (upperDownloadCallback != null) {
upperDownloadCallback.onResult(DOWN_START,filePath);
}
}
@Override
public void onFinish(String downloadUrl, String filePath) {
if (upperDownloadCallback != null) {
upperDownloadCallback.onResult(DOWN_FINISH,filePath);
}
}
@Override
public void onError(String error,String downloadUrl, String filePath) {
if (upperDownloadCallback != null) {
upperDownloadCallback.onResult(DOWN_ERROR,filePath);
}
}
}
package com.srthinker.statinfo.download.upper;
public interface UpperDownloadCallback {
void onProgress(String progress,String filePath);
void onResult(int downStatus,String filePath);
}
package com.srthinker.statinfo.listener;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import java.util.List;
public interface ConfigCallback {
void onUpdateConfig(List<ConfigEntity> configList, int type);
}
package com.srthinker.statinfo.listener;
import com.srthinker.statinfo.database.entity.PersonEntity;
import java.util.List;
public interface DeviceCallback {
void getPassInfo(List<PersonEntity> passEntities,int type);
void onConnectStatus(boolean isConnect,int type);
}
package com.srthinker.statinfo.listener;
public interface OnItemClickListener {
void OnItemClick(int position);
}
package com.srthinker.statinfo.listener;
import com.srthinker.statinfo.bean.TimeBean;
public interface OnTimeUpdateListener {
void OnTimeUpdate(TimeBean timeBean);
}
package com.srthinker.statinfo.listener;
public interface PersonMgrCallback {
void personUpdated();
}
package com.srthinker.statinfo.listener;
import com.srthinker.statinfo.database.entity.PersonEntity;
import java.util.List;
public interface QueryPersonCallback {
void onQueryStatus(String desc,boolean status);
void getTotalPerson(List<PersonEntity> personEntities, int type);
}
package com.srthinker.statinfo.listener.upper;
import com.srthinker.statinfo.database.entity.PersonEntity;
import java.util.List;
public interface UpperDevicesCallback {
void getAllPassInfo(List<PersonEntity> passAllEntities, int type);
void onAllConnectStatus(boolean hasConnect,int type);
}
package com.srthinker.statinfo.presenter;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.api.auth.AuthApi;
import com.srthinker.statinfo.api.kuangshi.api.auth.bean.LoginResp;
import com.srthinker.statinfo.api.kuangshi.api.auth.impl.AuthApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.pass.bean.PassQueryBean;
import com.srthinker.statinfo.api.kuangshi.api.pass.impl.PassApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonQueryResp;
import com.srthinker.statinfo.api.kuangshi.api.person.impl.PersonApiImpl;
import com.srthinker.statinfo.api.kuangshi.client.ApiClientException;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.listener.DeviceCallback;
import com.srthinker.statinfo.listener.QueryPersonCallback;
import com.srthinker.statinfo.util.common.DateUtil;
import com.srthinker.statinfo.util.common.ThreadPool;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
public class ApiManager {
private static final String TAG = "ApiManager";
private static final long GET_PASS_TIME = 60000;
private final String username;
private final String password;
private final String serverIp;
//private final DeviceCallback callback;
private final DefaultApiClient apiClient;
private final int type;
private final Handler handler;
private String sessionId;
private static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private DeviceCallback callback;
private PassApiImpl passApi;
private boolean isRunning = false; // 标记任务是否正在执行
private boolean isFirstStatus = false;
private int lastPassTotal;
private AuthApi authApi;
private PersonApiImpl personApi;
private boolean lastConnect = false;
private QueryPersonCallback queryPersonsCallback;
public ApiManager(String username, String password, String serverIp,int type){
this.username = username;
this.password = password;
this.serverIp = serverIp;
this.type = type;
//this.callback = callback;
String apiServerUrlPrefix = "http://" + serverIp;
//以设备为单位,每个设备都需要创建单独的DefaultApiClient
apiClient = new DefaultApiClient(apiServerUrlPrefix);
handler = new Handler();
//一个设备创建的api,都应该用同一个apiClient
authApi = new AuthApiImpl(apiClient);
personApi = new PersonApiImpl(apiClient);
passApi = new PassApiImpl(apiClient);
}
public void setOnDeviceCallback(DeviceCallback callback){
this.callback = callback;
}
public void setOnQueryPersonsCallback(QueryPersonCallback queryPersonsCallback){
this.queryPersonsCallback = queryPersonsCallback;
}
public void start(){
isRunning = true;
isFirstStatus = true;
lastConnect = false;
lastPassTotal = 0;
handler.post(authThreadRunnable);
//ThreadPool.getInstance().getThreadPoolExecutor().execute(passRecordRunnable);
handler.post(passThreadRunnable);
}
private Runnable authRunnable = new Runnable() {
@Override
public void run() {
//进行设备登录
// LoginResp loginResp = authApi.login("admin", "a12345");
LoginResp loginResp = null;
//boolean authConnect = false;
try {
loginResp = authApi.login(username, password);
if (loginResp != null) {
if(loginResp.getStatus() != 200) {
updateLastConnect(false);
//登录出错,打印错误信息
System.out.println(JSONObject.toJSONString(loginResp));
return;
}
sessionId = loginResp.getSessionId();
//只要连接成功都传避免出现意外,因为鉴权成功后也只访问一次
if (callback != null) {
lastConnect = true;
isFirstStatus = false;
callback.onConnectStatus(true, type);
}
//updateLastConnect(true);
Log.i(TAG, "run: sessionId==>"+ sessionId);
}
}catch (ApiClientException e2){
updateLastConnect(false);
} catch (Exception e) {
e.printStackTrace();
updateLastConnect(false);
Log.i(TAG, "run: authRunnable抛异常:ip="+serverIp);
if (isRunning){
handler.postDelayed(authThreadRunnable,2000);
}
}
}
};
//第一次和状态有变化的时候传
private void updateLastConnect(boolean newConnectStatus) {
if (lastConnect != newConnectStatus || isFirstStatus) {
lastConnect = newConnectStatus;
if (callback != null) {
callback.onConnectStatus(lastConnect, type);
}
isFirstStatus = false;
}
}
public void queryPersons(){
ThreadPool.getInstance().getThreadPoolExecutor().execute(() -> {
totalPersonLists = new ArrayList<>();
queryPerson();
Log.i(TAG, "queryPersons: 总人员查询完成开始回调");
//循环完了则进行回调总人数
if (queryPersonsCallback != null) {
queryPersonsCallback.getTotalPerson(totalPersonLists,type);
person_offset = 0;
}
});
}
private Runnable authThreadRunnable = new Runnable() {
@Override
public void run() {
ThreadPool.getInstance().getThreadPoolExecutor().execute(authRunnable);
}
};
private Runnable passRecordRunnable = new Runnable() {
@Override
public void run() {
/*if (TextUtils.isEmpty(sessionId)){
handler.post(this);
return;
}*/
totalPassLists = new ArrayList<>();
pass_offset = 0;
queryPass();
//Log.i(TAG, "run: totalPassLists.size()="+totalPassLists.size());
//Log.i(TAG, "run: lastPassTotal="+lastPassTotal);
if (totalPassLists.size()!=0&&totalPassLists.size()!= lastPassTotal){
if (callback != null) {
callback.getPassInfo(totalPassLists,type);
}
}
lastPassTotal = totalPassLists.size();
/*handler.postDelayed(this,60000);*/
}
};
private Runnable passThreadRunnable = new Runnable() {
@Override
public void run() {
if (TextUtils.isEmpty(sessionId)){
handler.post(this);
return;
}
ThreadPool.getInstance().getThreadPoolExecutor().execute(passRecordRunnable);
handler.postDelayed(this,GET_PASS_TIME);
}
};
private int passTotal = 0;
private int pass_offset = 0;
private int max_pass_limit = 128;
//private int max_pass_limit = 2;
private int passQuerySize = 0;
private List<PersonEntity> totalPassLists = new ArrayList<>();
private void queryPass(){
//获取历史通行记录
// Log.i(TAG, "start: passApi="+passApi);
String begin_time = DateUtil.getDateFormattedZone(new Date(), "yyyy-MM-dd");
String end_time = DateUtil.getDateFormattedZone(DateUtil.getNextDate(), "yyyy-MM-dd");
if (TextUtils.isEmpty(sessionId)){
//handler.post(this);
//return;
}else{
PassQueryBean passQueryResp = null;
try {
passQueryResp = passApi.query(max_pass_limit,pass_offset,"desc", begin_time, end_time);
if (passQueryResp!=null){
//Log.i(TAG, "run: passQueryResp="+passQueryResp.toString());
if (passQueryResp.getPaging()==null&&passQueryResp.getData()==null&&passQueryResp.getQuery_id()==null){
//重新再登录鉴权一下:
Log.i(TAG, "run: passQueryResp不为空,内容为空时也重新鉴权");
if (isRunning) {
handler.post(authThreadRunnable);
}
//清空重新循环
person_offset = 0;
pass_offset = 0;
}
List<PassQueryBean.DataBean> dataBeanList = passQueryResp.getData();
List<PersonEntity> passBeans = new ArrayList<>();
if (dataBeanList!=null){
for (PassQueryBean.DataBean dataBean : dataBeanList) {
PersonEntity passBean = new PersonEntity();
passBean.setId(dataBean.getPerson_id());
passBean.setPerson_name(dataBean.getPerson_name());
String timestamp = dataBean.getTimestamp();
String timeString = DateUtil.zoneToDateString(timestamp, "HH:mm");
passBean.setTimestamp(timeString);
passBeans.add(passBean);
}
totalPassLists.addAll(passBeans);
updateLastConnect(true);
}
PassQueryBean.PagingBean paging = passQueryResp.getPaging();
if (paging!=null){
passTotal = paging.getTotal();
passQuerySize = paging.getLimit();
pass_offset += passQuerySize;
while (passQuerySize>0 && passQuerySize<passTotal&&pass_offset<passTotal){
queryPass();
}
}
}
} catch (ApiClientException e2){
updateLastConnect(false);
} catch (Exception e) {
Log.i(TAG, "run: passRecordRunnable抛异常");
updateLastConnect(false);
e.printStackTrace();
}
}
}
private int personTotal = 0;
private int person_offset = 0;
private int max_person_limit = 100;
//private int max_person_limit = 2;
private int personQuerySize;
private List<PersonEntity> totalPersonLists = new ArrayList<>();
private void queryPerson(){
//不管是asc还是desc,都是正排序
PersonQueryResp personQueryResp = null;
Log.i(TAG, "queryPerson: 开始查询人员数量");
try {
personQueryResp = personApi.query(max_person_limit, person_offset, "asc");
} catch (ApiClientException e2){
} catch (Exception e) {
e.printStackTrace();
Log.i(TAG, "run: queryPerson抛异常:ip="+serverIp);
/*if (callback != null) {
callback.onConnectStatus(false,type);
}*/
if (queryPersonsCallback != null) {
queryPersonsCallback.onQueryStatus("查询接口失败!",false);
}
}
if (personQueryResp!=null){
if (personQueryResp.getData()==null&&personQueryResp.getQuery_id()==null&&personQueryResp.getPaging()==null){
//重新再登录鉴权一下:
Log.i(TAG, "run: personQueryResp不为空,内容为空时也重新鉴权");
handler.post(authThreadRunnable);
//清空重新循环
person_offset = 0;
pass_offset = 0;
//handler.postDelayed(personThreadRunnable,2000);
}
List<PersonQueryResp.DataBean> personDataList = personQueryResp.getData();
if (personDataList != null) {
List<PersonEntity> personEntities = new ArrayList<>();
for (PersonQueryResp.DataBean personData : personDataList) {
//
PersonEntity personEntity = new PersonEntity();
personEntity.setId(personData.getId());
personEntity.setPerson_name(personData.getPerson_name());
personEntities.add(personEntity);
}
totalPersonLists.addAll(personEntities);
}
PersonQueryResp.PagingBean pagingBean = personQueryResp.getPaging();
if (pagingBean != null) {
personTotal = pagingBean.getTotal();
personQuerySize = pagingBean.getLimit();
person_offset+= personQuerySize;
while (personQuerySize >0 && personQuerySize <personTotal && person_offset<personTotal){
queryPerson();
}
}
}
}
public void stop(){
Log.i(TAG, "stop: 停止连接接口:ip="+serverIp);
//handler.removeCallbacks(passRunnable);
handler.removeCallbacks(passThreadRunnable);
handler.removeCallbacks(passRecordRunnable);
handler.removeCallbacks(authThreadRunnable);
handler.removeCallbacks(authRunnable);
isRunning = false;
}
}
package com.srthinker.statinfo.presenter;
import static com.srthinker.statinfo.constant.InOutType.ENTER_TYPE;
import static com.srthinker.statinfo.constant.InOutType.LEAVE_TYPE;
import android.util.Log;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.helper.ConfigHelper;
import com.srthinker.statinfo.listener.DeviceCallback;
import com.srthinker.statinfo.listener.QueryPersonCallback;
import com.srthinker.statinfo.listener.upper.UpperDevicesCallback;
import com.srthinker.statinfo.util.common.ThreadPool;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
public class ApiQuest {
private static final String TAG = "ApiQuest";
private static ApiQuest apiQuest;
private static boolean isEnterAllConnect = false;
private static boolean isLeaveAllConnect = false;
private static LinkedHashMap<String,Boolean> enterIpStatus = new LinkedHashMap<>();
private static LinkedHashMap<String,Boolean> leaveIpStatus = new LinkedHashMap<>();
private static List<PersonEntity> allEnterPass = new ArrayList<>();
private static List<PersonEntity> allLeavePass = new ArrayList<>();
private UpperDevicesCallback upperDevicesCallback;
private static LinkedHashMap<String,ApiManager> enterMgrHashMap = new LinkedHashMap<>();
private static LinkedHashMap<String,ApiManager> leaveMgrHashMap = new LinkedHashMap<>();
private String oneEnterIp;
public static ApiQuest getInstance(){
if (apiQuest == null) {
synchronized (ApiQuest.class){
apiQuest = new ApiQuest();
}
}
return apiQuest;
}
public void setOnUpperDevicesCallback(UpperDevicesCallback upperDevicesCallback){
this.upperDevicesCallback = upperDevicesCallback;
}
private void initData(int type){
if (type==ENTER_TYPE){
isEnterAllConnect = false;
allEnterPass = new ArrayList<>();
}else if (type==LEAVE_TYPE){
isLeaveAllConnect = false;
allLeavePass = new ArrayList<>();
}
}
public void startApi(List<ConfigEntity> configList,int type){
if (configList != null) {
synchronized (this){
//把之前的所有的停掉
stopApiByType(type);
initData(type);
for (int i = 0; i < configList.size(); i++) {
ConfigEntity config = configList.get(i);
String username = config.getUsername();
String password = config.getPassword();
String serverIp = config.getServerIp();
if (i==0&&type==ENTER_TYPE){
oneEnterIp = serverIp;
}
if (type==ENTER_TYPE){
startEnterIp(username,password,serverIp);
}else if (type==LEAVE_TYPE){
startLeaveIp(username,password,serverIp);
}
}
}
}
}
private void startEnterIp(String username, String password, String ip) {
Log.i(TAG, "startEnterIp: 访问接口的ip="+ip);
/*//如果之前有过则停掉
if (enterMgrHashMap.containsKey(ip)){
ApiManager apiManager = enterMgrHashMap.get(ip);
if (apiManager != null) {
apiManager.stop();
}
enterMgrHashMap.remove(ip);
}*/
ApiManager enterMgr = new ApiManager(username, password, ip, ENTER_TYPE);
enterMgrHashMap.put(ip,enterMgr);
enterMgr.start();
enterMgr.setOnDeviceCallback(new DeviceCallback() {
@Override
public void getPassInfo(List<PersonEntity> passEntities, int type) {
synchronized (allEnterPass){
allEnterPass.addAll(passEntities);
/*for (PersonEntity enterPass : allEnterPass) {
Log.i(TAG, "去重前getPassInfo: enterPass.time="+enterPass.getTimestamp()+",name="+enterPass.getPerson_name());
}*/
PersonEntityComparator comparator = new PersonEntityComparator();
Collections.sort(allEnterPass,comparator);
LinkedHashSet<PersonEntity> mergeList = new LinkedHashSet<>(allEnterPass);
allEnterPass = new ArrayList<>(mergeList);
/*for (PersonEntity enterPass : allEnterPass) {
Log.i(TAG, "去重后getPassInfo: enterPass.time="+enterPass.getTimestamp()+",name="+enterPass.getPerson_name());
}*/
ArrayList<PersonEntity> allPassList = new ArrayList<>(allEnterPass);
if (upperDevicesCallback != null) {
upperDevicesCallback.getAllPassInfo(allPassList,type);
}
}
}
@Override
public void onConnectStatus(boolean isConnect, int type) {
Log.i(TAG, "onConnectStatus: 接收到的连接状态:isConnect="+isConnect+",ip="+ip);
ThreadPool.getInstance().getThreadPoolExecutor().execute(() -> {
//修改状态
List<ConfigEntity> configEntities = ConfigHelper.getInstance().queryByTypeIp(type, ip);
synchronized (configEntities){
for (ConfigEntity configEntity : configEntities) {
configEntity.setConnect(isConnect);
//Log.i(TAG, "onConnectStatus: 修改后:ip"+configEntity.getServerIp()+",isConnect="+configEntity.isConnect());
//更新ip接口状态
ConfigHelper.getInstance().update(configEntity);
}
}
//获取最新状态
List<ConfigEntity> enterList = ConfigHelper.getInstance().queryByType(type);
isEnterAllConnect = true;
synchronized (enterList){
for (ConfigEntity config : enterList) {
//Log.i(TAG, "onConnectStatus: 数据库里面的数据:ip="+config.getServerIp()+",isConnect="+config.isConnect());
boolean connect = config.isConnect();
if (!connect){
isEnterAllConnect = false;
break;
}
}
if (upperDevicesCallback != null) {
upperDevicesCallback.onAllConnectStatus(isEnterAllConnect,type);
}
}
});
}
});
}
private void startLeaveIp(String username, String password, String ip) {
//如果之前有过则停掉
/*if (leaveMgrHashMap.get(ip)!=null){
ApiManager apiManager = leaveMgrHashMap.get(ip);
if (apiManager != null) {
apiManager.stop();
}
leaveMgrHashMap.remove(ip);
}*/
ApiManager leaveMgr = new ApiManager(username, password, ip, LEAVE_TYPE);
leaveMgrHashMap.put(ip,leaveMgr);
leaveMgr.start();
leaveMgr.setOnDeviceCallback(new DeviceCallback() {
@Override
public void getPassInfo(List<PersonEntity> passEntities, int type) {
synchronized (allLeavePass){
allLeavePass.addAll(passEntities);
PersonEntityComparator comparator = new PersonEntityComparator();
Collections.sort(allLeavePass,comparator);
LinkedHashSet<PersonEntity> mergeList = new LinkedHashSet<>(allLeavePass);
allLeavePass = new ArrayList<>(mergeList);
ArrayList<PersonEntity> allPassList = new ArrayList<>(allLeavePass);
if (upperDevicesCallback != null) {
upperDevicesCallback.getAllPassInfo(allPassList,type);
}
}
}
@Override
public void onConnectStatus(boolean isConnect, int type) {
Log.i(TAG, "onConnectStatus: 接收到的连接状态:isConnect="+isConnect+",ip="+ip);
ThreadPool.getInstance().getThreadPoolExecutor().execute(() -> {
//修改状态
List<ConfigEntity> configEntities = ConfigHelper.getInstance().queryByTypeIp(type, ip);
synchronized (configEntities){
for (ConfigEntity configEntity : configEntities) {
configEntity.setConnect(isConnect);
//Log.i(TAG, "onConnectStatus: 修改后:ip"+configEntity.getServerIp()+",isConnect="+configEntity.isConnect());
//更新ip接口状态
ConfigHelper.getInstance().update(configEntity);
}
}
//获取最新状态
List<ConfigEntity> leaveList = ConfigHelper.getInstance().queryByType(type);
isLeaveAllConnect = true;
synchronized (leaveList){
for (ConfigEntity config : leaveList) {
//Log.i(TAG, "onConnectStatus: 数据库里面的数据:ip="+config.getServerIp()+",isConnect="+config.isConnect());
boolean connect = config.isConnect();
if (!connect){
isLeaveAllConnect = false;
break;
}
}
if (upperDevicesCallback != null) {
upperDevicesCallback.onAllConnectStatus(isLeaveAllConnect,type);
}
}
});
}
});
}
public void stopApi(){
stopApiByType(ENTER_TYPE);
stopApiByType(LEAVE_TYPE);
}
public void stopApiByType(int type) {
LinkedHashMap<String, ApiManager> mgrHashMap = type == ENTER_TYPE ? enterMgrHashMap : leaveMgrHashMap;
for (Map.Entry<String, ApiManager> mgr : mgrHashMap.entrySet()) {
ApiManager apiManager = mgr.getValue();
if (apiManager != null) {
apiManager.stop();
apiManager.setOnDeviceCallback(null);
apiManager = null;
}
}
mgrHashMap.clear();
}
public void queryPersons(QueryPersonCallback callback){
if (enterMgrHashMap.size()>0){
ApiManager oneEnterMgr = enterMgrHashMap.get(oneEnterIp);
if (oneEnterMgr != null) {
oneEnterMgr.queryPersons();
oneEnterMgr.setOnQueryPersonsCallback(callback);
}
}
}
}
package com.srthinker.statinfo.presenter;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.util.common.DateUtil;
import java.util.Comparator;
public class PersonEntityComparator implements Comparator<PersonEntity> {
@Override
public int compare(PersonEntity p1, PersonEntity p2) {
long time1 = DateUtil.getTime(p1.getTimestamp(), "HH:mm");
long time2 = DateUtil.getTime(p2.getTimestamp(), "HH:mm");
//从大到小排列
if (time1>time2){
return -1;
}else if (time1<time2){
return 1;
}else{
return 0;
}
}
}
package com.srthinker.statinfo.presenter;
import android.os.Handler;
import android.text.TextUtils;
import com.srthinker.statinfo.bean.TimeBean;
import com.srthinker.statinfo.listener.OnTimeUpdateListener;
import com.srthinker.statinfo.util.common.DateUtil;
public class RealTimeClock {
private Handler handler;
private OnTimeUpdateListener onTimeUpdateListener;
private String lastTime;
public RealTimeClock(){
this.handler = new Handler();
}
public void setOnTimeUpdateListener(OnTimeUpdateListener onTimeUpdateListener){
this.onTimeUpdateListener = onTimeUpdateListener;
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
String nowDateTime = DateUtil.getNowDateTime("yyyy/MM/dd HH:mm:ss");
String nowWeekString = DateUtil.getNowWeekString();
if (onTimeUpdateListener!=null && !TextUtils.equals(lastTime,nowDateTime)){
TimeBean timeBean = new TimeBean();
String[] s = nowDateTime.split(" ");
timeBean.setyMD(s[0]);
timeBean.setHm(s[1]);
timeBean.setWeek(nowWeekString);
onTimeUpdateListener.OnTimeUpdate(timeBean);
lastTime = nowDateTime;
}
handler.postDelayed(this,1000);
}
};
public void start(){
handler.post(runnable);
}
public void stop(){
handler.removeCallbacks(runnable);
}
}
package com.srthinker.statinfo.presenter;
import com.srthinker.statinfo.database.entity.PersonEntity;
import java.util.ArrayList;
import java.util.List;
public class StatSize {
//id和时间相同的进行去重过滤
public static List<PersonEntity> filterList(List<PersonEntity> personEntityList){
List<PersonEntity> filterPersonList = new ArrayList<>();
if (personEntityList != null) {
for (PersonEntity personEntity : personEntityList) {
boolean shouldAdd = true;
for (PersonEntity entity : filterPersonList) {
if (equals(personEntity.getId(),entity.getId())&&equals(personEntity.getTimestamp(),entity.getTimestamp())){
shouldAdd = false;
break;
}
}
if (shouldAdd){
filterPersonList.add(personEntity);
}
}
}
return filterPersonList;
}
private static boolean equals(String str1, String str2) {
if (str1 == null && str2 == null) {
return true;
} else if (str1 == null || str2 == null) {
return false;
} else {
return str1.equals(str2);
}
}
}
package com.srthinker.statinfo.uis;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.LayoutRes;
import androidx.appcompat.app.AppCompatActivity;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.databinding.ActivityBaseBinding;
import com.srthinker.statinfo.util.common.StatusBarUtil;
import com.srthinker.statinfo.util.common.Utils;
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityBaseBinding inflate = ActivityBaseBinding.inflate(getLayoutInflater());
setContentView(inflate.getRoot());
setStatusBar();
Utils.autoSizeSwitch(this);
}
protected void setStatusBar() {
StatusBarUtil.hideSystemUI(this);
}
protected abstract void initData();
protected abstract void initView();
public void setTheView(@LayoutRes int layoutId){
LayoutInflater.from(this).inflate(layoutId,this.findViewById(R.id.baseContentView));
}
protected void releaseRes(){
}
@Override
protected void onDestroy() {
releaseRes();
super.onDestroy();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideKeyboard(v, ev)) {
hideKeyboard(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
/**
* 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏
*
* @param v
* @param event
* @return
*/
private boolean isShouldHideKeyboard(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0],
top = l[1],
bottom = top + v.getHeight(),
right = left + v.getWidth();
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
// 点击EditText的事件,忽略它。
return false;
} else {
return true;
}
}
// 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
return false;
}
/**
* 获取InputMethodManager,隐藏软键盘
*
* @param token
*/
private void hideKeyboard(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
public void showTips(String tips){
Toast.makeText(this.getApplicationContext(), tips, Toast.LENGTH_SHORT).show();
}
}
\ No newline at end of file
package com.srthinker.statinfo.uis;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.srthinker.statinfo.R;
public class FlashActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
}
}
\ No newline at end of file
package com.srthinker.statinfo.uis;
import android.os.Bundle;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.bean.TimeBean;
import com.srthinker.statinfo.databinding.ActivityGroupBinding;
import com.srthinker.statinfo.databinding.LayoutTopBinding;
import com.srthinker.statinfo.listener.OnTimeUpdateListener;
import com.srthinker.statinfo.presenter.RealTimeClock;
import com.srthinker.statinfo.uis.fragment.GroupFragment;
public class GroupActivity extends BaseActivity implements OnTimeUpdateListener {
private com.srthinker.statinfo.databinding.ActivityGroupBinding mBinding;
private com.srthinker.statinfo.databinding.LayoutTopBinding topBinding;
private RealTimeClock mRealTimeClock;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_group);
mBinding = ActivityGroupBinding.inflate(getLayoutInflater());
topBinding = LayoutTopBinding.bind(mBinding.getRoot());
setContentView(mBinding.getRoot());
initData();
initView();
}
@Override
protected void initData() {
}
@Override
protected void initView() {
updateTime();
switchFrag();
}
private void switchFrag() {
getSupportFragmentManager().beginTransaction().replace(R.id.fcv_main,new GroupFragment(),GroupFragment.class.getSimpleName())
.commitAllowingStateLoss();
}
private void updateTime() {
mRealTimeClock = new RealTimeClock();
mRealTimeClock.setOnTimeUpdateListener(this);
mRealTimeClock.start();
}
@Override
public void OnTimeUpdate(TimeBean timeBean) {
topBinding.tvTime.setText(timeBean.getyMD()+" "+timeBean.getWeek()+" "+timeBean.getHm());
}
}
\ No newline at end of file
package com.srthinker.statinfo.uis;
import static com.srthinker.statinfo.constant.Const.DEVICE_TYPE;
import static com.srthinker.statinfo.constant.GroupConst.BUILD;
import static com.srthinker.statinfo.constant.GroupConst.BUILD_ID;
import static com.srthinker.statinfo.constant.GroupConst.OUTRIGGER;
import static com.srthinker.statinfo.constant.GroupConst.OUTRIGGER_ID;
import static com.srthinker.statinfo.constant.GroupConst.SUPERVISOR;
import static com.srthinker.statinfo.constant.GroupConst.SUPERVISOR_ID;
import static com.srthinker.statinfo.constant.GroupConst.WATERPROOF;
import static com.srthinker.statinfo.constant.GroupConst.WATERPROOF_ID;
import static com.srthinker.statinfo.constant.InOutType.ENTER_TYPE;
import static com.srthinker.statinfo.constant.InOutType.LEAVE_TYPE;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_ERROR;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_FINISH;
import static com.srthinker.statinfo.download.upper.DownStatus.DOWN_START;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.adapter.EnterAdapter;
import com.srthinker.statinfo.adapter.GroupAdapter;
import com.srthinker.statinfo.adapter.LeaveAdapter;
import com.srthinker.statinfo.bean.GroupBean;
import com.srthinker.statinfo.bean.TimeBean;
import com.srthinker.statinfo.database.PersonMgr;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.helper.ConfigHelper;
import com.srthinker.statinfo.database.helper.PersonHelper;
import com.srthinker.statinfo.databinding.ActivityMainBinding;
import com.srthinker.statinfo.download.upper.DownloadViewModel;
import com.srthinker.statinfo.download.upper.UpperDownloadCallback;
import com.srthinker.statinfo.listener.ConfigCallback;
import com.srthinker.statinfo.listener.OnTimeUpdateListener;
import com.srthinker.statinfo.listener.QueryPersonCallback;
import com.srthinker.statinfo.listener.upper.UpperDevicesCallback;
import com.srthinker.statinfo.presenter.ApiManager;
import com.srthinker.statinfo.presenter.ApiQuest;
import com.srthinker.statinfo.presenter.RealTimeClock;
import com.srthinker.statinfo.presenter.StatSize;
import com.srthinker.statinfo.uis.fragment.ConfigDlgFragment;
import com.srthinker.statinfo.update.MDownloadCallBack;
import com.srthinker.statinfo.update.NetworkViewModel;
import com.srthinker.statinfo.update.UpdateInfo;
import com.srthinker.statinfo.util.common.ClickUtil;
import com.srthinker.statinfo.util.common.FileUtil;
import com.srthinker.statinfo.util.common.GsonUtil;
import com.srthinker.statinfo.util.common.PermissionUtil;
import com.srthinker.statinfo.util.common.SharedUtil;
import com.srthinker.statinfo.util.common.ThreadPool;
import com.srthinker.statinfo.util.common.Utils;
import com.srthinker.statinfo.util.other.NetworkIPMonitor;
import com.srthinker.statinfo.wedget.LoadDialog;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
public class MainActivity extends BaseActivity implements OnTimeUpdateListener, MDownloadCallBack, UpperDownloadCallback, NetworkIPMonitor.OnIPChangeCallback, ConfigCallback, QueryPersonCallback, UpperDevicesCallback {
private static final String TAG = "MainActivity";
private com.srthinker.statinfo.databinding.ActivityMainBinding mBinding;
private RealTimeClock mRealTimeClock;
private List<PersonEntity> enterBeans;
private List<PersonEntity> leaveBeans;
private EnterAdapter enterAdapter;
private LeaveAdapter leaveAdapter;
private NetworkIPMonitor networkIPMonitor;
private String installPath = "";
private LoadDialog mLoadDialog;
//private String savePath = "/sdcard/update/StatInfo.apk";
//getFilesDir() + "/update", "StatInfo.apk"
private String savePath = Environment.getExternalStorageDirectory().getPath() + "/update";
private String sessionId;
private ApiManager enterMgr;
private static ScheduledExecutorService executor;
private int lastEnterSize = 0;
private int lastLeaveSize = 0;
private int lastPresentSize = 0;
private String deviceSn;
private List<PersonEntity> mQueryPersonList;
private GroupAdapter groupAdapter;
private HashMap<Integer, Integer> groupEnterHashMap=null;
private HashMap<Integer, Integer> groupLeaveHashMap=null;
private HashMap<Integer,Integer> groupPresentHashMap=null;
private boolean isPermission;
public static boolean NEED_NO_REPET = true; //是否需要去重,false:不需要,true:需要
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
mBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mBinding.getRoot());
initData();
initView();
checkAllPermission();
}
@SuppressLint("SdCardPath")
@Override
protected void initData() {
//获取Sn
deviceSn = FileUtil.readTextFromFile("/sdcard/devicesn/deviceSn.txt");
networkIPMonitor = new NetworkIPMonitor(this);
enterBeans = new ArrayList<>();
leaveBeans = new ArrayList<>();
/*for (int i = 0; i < 12; i++) {
enterBeans.add(new PeopleBean("08:14","王大锤"));
}
for (int i = 0; i < 5; i++) {
leaveBeans.add(new PeopleBean("08:04","赵美丽"));
}*/
networkIPMonitor.startMonitoring();
networkIPMonitor.setOnIPChangeCallback(this);
}
@SuppressLint("SetTextI18n")
@Override
protected void initView() {
initNumber();
updateTime();
initGroup();
initPeopleList();
//mLoadDialog = LoadDialog.getInstance(this);
mLoadDialog = new LoadDialog(this);
//Log.i(TAG, "initView: deviceSn="+deviceSn+"V"+ Utils.getVersionName(this));
mBinding.tvDeviceDesc.setText(DEVICE_TYPE+" "+deviceSn+" V"+ Utils.getVersionName(this));
//getResp();
mBinding.tvEnterText.setOnClickListener(v->{
showConfigDialog(ENTER_TYPE);
});
mBinding.tvLeaveText.setOnClickListener(v->{
showConfigDialog(LEAVE_TYPE);
});
mBinding.btnGroupDetail.setOnClickListener(v->{
ApiQuest.getInstance().queryPersons(this);
ClickUtil.disableClick(mBinding.btnGroupDetail);
});
}
private void showConfigDialog(int type) {
ConfigDlgFragment configDlgFragment = ConfigDlgFragment.getInstance(type);
configDlgFragment.setUsername("admin");
configDlgFragment.setConfigCallback(this);
if (configDlgFragment.isResumed()){
return;
}
configDlgFragment.showNow(getSupportFragmentManager(),configDlgFragment.getClass().getSimpleName());
configDlgFragment.setCancelable(false);
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: Main-Resume");
//获取最新的人员信息列表
mQueryPersonList = PersonHelper.getInstance().queryAll();
//更新分组情况
groupEnterHashMap = getGroupSizeHashMap(enterBeans);
groupLeaveHashMap = getGroupSizeHashMap(leaveBeans);
updatePresentSize(groupEnterHashMap,groupLeaveHashMap);
detectUpgrade(); //检测版本升级
}
@Override
protected void onDestroy() {
Log.i(TAG, "onDestroy: Main--destroy");
networkIPMonitor.stopMonitoring();
mRealTimeClock.stop();
//关闭循环拉取
//executor.shutdownNow();
/*if (enterMgr != null) {
enterMgr.stop();
}*/
ApiQuest.getInstance().stopApi();
super.onDestroy();
}
private void detectUpgrade() {
NetworkViewModel networkViewModel = new NetworkViewModel();
networkViewModel.init(this,this);
networkViewModel.setDownloadCallback(this);
networkViewModel.getLastestVersion(deviceSn,DEVICE_TYPE);
}
private void checkAllPermission() {
isPermission = PermissionUtil.checkMultiPermission(this, new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.INTERNET
}, 4096);
if (!isPermission){
Toast.makeText(this, "需要允许权限才能正常使用哦", Toast.LENGTH_SHORT).show();
}
}
private void initNumber() {
mBinding.nvEnter.initItem(lastEnterSize,"进去人数", R.mipmap.enter_bg);
mBinding.nvLeave.initItem(lastLeaveSize,"离开人数", R.mipmap.leave_bg);
mBinding.nvPresent.initItem(lastPresentSize,"在场人数", R.mipmap.present_bg);
}
private void initPeopleList() {
LinearLayoutManager enterLLM = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
mBinding.rvEnterList.setLayoutManager(enterLLM);
enterAdapter = new EnterAdapter(this, enterBeans);
mBinding.rvEnterList.setAdapter(enterAdapter);
LinearLayoutManager leaveLLM = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
mBinding.rvLeaveList.setLayoutManager(leaveLLM);
leaveAdapter = new LeaveAdapter(this, leaveBeans);
mBinding.rvLeaveList.setAdapter(leaveAdapter);
}
private void initGroup() {
GridLayoutManager groupGLM = new GridLayoutManager(this, 4);
mBinding.rvGroup.setLayoutManager(groupGLM);
ArrayList<GroupBean> groupBeans = updateGroup();
groupAdapter = new GroupAdapter(this, groupBeans);
mBinding.rvGroup.setAdapter(groupAdapter);
/*mBinding.gvWaterproof.initItem("防水班组",34,R.color.color_2D52E3);
mBinding.gvOutrigger.initItem("外架班组",12,R.color.color_694BFF);
mBinding.gvBuild.initItem("工地班组",26,R.color.color_8A34D5);
mBinding.gvSupervisor.initItem("监理单位",28,R.color.color_00A89C);*/
}
private ArrayList<GroupBean> updateGroup() {
ArrayList<GroupBean> groupBeans = new ArrayList<>();
int waterproof = SharedUtil.getInstance(this).readShared(WATERPROOF, 0);
int outrigger = SharedUtil.getInstance(this).readShared(OUTRIGGER, 0);
int build = SharedUtil.getInstance(this).readShared(BUILD, 0);
int supervisor = SharedUtil.getInstance(this).readShared(SUPERVISOR, 0);
groupBeans.add(new GroupBean("防水班组",waterproof,R.color.color_2D52E3,WATERPROOF));
groupBeans.add(new GroupBean("外架班组",outrigger,R.color.color_694BFF,OUTRIGGER));
groupBeans.add(new GroupBean("工地班组",build,R.color.color_8A34D5,BUILD));
groupBeans.add(new GroupBean("监理单位",supervisor,R.color.color_00A89C,SUPERVISOR));
return groupBeans;
}
private void updateTime() {
mRealTimeClock = new RealTimeClock();
mRealTimeClock.setOnTimeUpdateListener(this);
mRealTimeClock.start();
}
@SuppressLint("SetTextI18n")
@Override
public void OnTimeUpdate(TimeBean timeBean) {
if (timeBean != null) {
mBinding.tvTime.setText(timeBean.getyMD()+" "+timeBean.getWeek()+" "+timeBean.getHm());
}
}
@Override
public void checkResult(boolean needUpdate, boolean canInstall, UpdateInfo onlineInfo) {
if (needUpdate){
if (onlineInfo!=null){
Log.i(TAG, "checkResult: onlineInfo="+ GsonUtil.toJsonString(onlineInfo));
//Environment.getExternalStorageDirectory().getPath()=/storage/emulated/0
//getFilesDir()=installPath=/data/user/0/com.srthinker.statinfo/files
//String installPath = getFilesDir() + "/" + "StatInfo.apk";
//boolean isCreate = FileUtil.createFile(getFilesDir() + "/update", "StatInfo.apk");
FileUtil.deleteFile(savePath+File.separator+"StatInfo.apk");
boolean isCreate = FileUtil.createFile( savePath+File.separator, "StatInfo.apk");
if (isCreate){
//installPath = getFilesDir()+"/update/StatInfo.apk";
installPath = savePath+File.separator+"StatInfo.apk";
DownloadViewModel downloadViewModel = new DownloadViewModel(this);
downloadViewModel.initData();
downloadViewModel.startDownload(onlineInfo.getDownloadUrl(),installPath);
downloadViewModel.setOnUpperDownloadCallback(this);
}
}
}
}
@Override
public void onProgress(String progress, String filePath) {
runOnUiThread(()->{
//Log.i(TAG, "onProgress: progress="+progress);
String desc = "下载更新中..."+progress;
if (mLoadDialog != null) {
mLoadDialog.setContent(desc);
mLoadDialog.showDialog();
}
});
}
@Override
public void onResult(int downStatus, String filePath) {
runOnUiThread(()->{
if (downStatus == DOWN_START){
String desc = "准备下载更新";
if (mLoadDialog != null) {
mLoadDialog.setContent(desc);
mLoadDialog.showDialog();
}
} else if (downStatus== DOWN_FINISH){
//安装更新
//Log.i(TAG, "onResult:进来多少次");
//showTips("更新版本,将进行安装");
String desc = "进行安装,请稍等";
if (mLoadDialog != null) {
mLoadDialog.setContent(desc);
mLoadDialog.showDialog();
}
//Utils.installApp(getApplicationContext(),new File(installPath));
//有静默安装的话需要开新线程,不然前面的弹框不进行显示
ThreadPool.getInstance().getThreadPoolExecutor().execute(() -> {
boolean restricted = Utils.isRootPermissionRestricted();
if (!restricted){
Utils.clientInstall(installPath,MainActivity.this,".uis.MainActivity");
}else{
Utils.installApp(getApplicationContext(),new File(installPath));
}
runOnUiThread(()->{
if (mLoadDialog != null) {
mLoadDialog.dismissDialog();
mLoadDialog=null;
}
});
});
}else if (downStatus==DOWN_ERROR){
showTips("下载更新失败");
FileUtil.deleteFile(installPath);
}
});
}
private void updatePassInfo(List<PersonEntity> passEntities, int type) {
Log.i(TAG, "updatePassInfo: 获取的总数="+passEntities.size());
/*for (PersonEntity passEntity : passEntities) {
Log.i(TAG, "updatePassInfo: 获取到的name="+passEntity.getPerson_name());
}*/
if (type ==ENTER_TYPE){
if (passEntities != null) {
if (enterAdapter != null) {
int size = passEntities.size();
if (enterBeans!=null&&size!=enterBeans.size()){
//更新进出情况
//enterBeans = passEntities; 全局变量直接赋值会出现问题
enterBeans.clear();
enterBeans.addAll(passEntities);
enterAdapter.setDataList(passEntities);
//更新人员情况(是否要根据id去重)
if (NEED_NO_REPET) {
List<PersonEntity> enterListNo = StatSize.filterList(passEntities);
lastEnterSize = enterListNo.size();
}else{
lastEnterSize = size;
}
lastPresentSize = lastEnterSize-lastLeaveSize;
mBinding.nvEnter.setNumber(lastEnterSize);
mBinding.nvLeave.setNumber(lastLeaveSize);
mBinding.nvPresent.setNumber(lastPresentSize);
//更新分组情况(是否要根据id去重)
groupEnterHashMap = getGroupSizeHashMap(passEntities);
updatePresentSize(groupEnterHashMap,groupLeaveHashMap);
}
/* Log.i(TAG, "updatePassInfo: enterBeans.size="+enterBeans.size());
Log.i(TAG, "updatePassInfo: adapter.size="+enterAdapter.getDataList().size());*/
}
}
}else if (type == LEAVE_TYPE){
//leaveBeans = passEntities;
if (passEntities != null) {
if (leaveAdapter != null) {
int size = passEntities.size();
//进出有变化时才更新
if (leaveBeans!=null&&size!=leaveBeans.size()){
leaveBeans.clear();
leaveBeans.addAll(passEntities);
//更新进出情况
leaveAdapter.setDataList(passEntities);
//更新人员情况(是否要根据id去重)
if (NEED_NO_REPET) {
List<PersonEntity> leaveListNo = StatSize.filterList(passEntities);
lastLeaveSize = leaveListNo.size();
}else{
lastLeaveSize = size;
}
lastPresentSize = lastEnterSize-lastLeaveSize;
mBinding.nvEnter.setNumber(lastEnterSize);
mBinding.nvLeave.setNumber(lastLeaveSize);
mBinding.nvPresent.setNumber(lastPresentSize);
//更新分组情况(是否要根据id去重)
groupLeaveHashMap = getGroupSizeHashMap(passEntities);
updatePresentSize(groupEnterHashMap,groupLeaveHashMap);
}
/*Log.i(TAG, "updatePassInfo: leaveBeans.size="+leaveBeans.size());
Log.i(TAG, "updatePassInfo: adapter.size="+leaveAdapter.getDataList().size());*/
}
}
}
}
@NonNull
private HashMap<Integer, Integer> getGroupSizeHashMap(List<PersonEntity> personEntityList) {
HashMap<Integer, Integer> groupSizeHashMap = new HashMap<>();
if (NEED_NO_REPET) {
personEntityList = StatSize.filterList(personEntityList);
}
if (mQueryPersonList != null) {
for (PersonEntity entity : mQueryPersonList) {
int group = entity.getGroup();
if (!groupSizeHashMap.containsKey(group)){
groupSizeHashMap.put(group,0);
}
}
for (PersonEntity personEntity : personEntityList) {
String personId = personEntity.getId();
for (PersonEntity queryPerson : mQueryPersonList) {
String queryId = queryPerson.getId();
int group = queryPerson.getGroup();
if (TextUtils.equals(personId,queryId)&& groupSizeHashMap.containsKey(group)){
int totalSize = groupSizeHashMap.get(group);
groupSizeHashMap.put(group,totalSize+1);
}
}
}
}
return groupSizeHashMap;
}
private void updatePresentSize(HashMap<Integer,Integer> groupEnterHashMap,HashMap<Integer,Integer> groupLeaveHashMap){
groupPresentHashMap = new HashMap<>();
if (mQueryPersonList != null) {
for (PersonEntity entity : mQueryPersonList) {
int group = entity.getGroup();
if (!groupPresentHashMap.containsKey(group)) {
groupPresentHashMap.put(group, 0);
}
}
}
//更新分组情况
if (groupEnterHashMap != null) {
for (Map.Entry<Integer, Integer> enterEntry : groupEnterHashMap.entrySet()) {
int group = enterEntry.getKey();
int enterSize = enterEntry.getValue();
groupPresentHashMap.put(group,enterSize);
}
}
if (groupLeaveHashMap != null) {
for (Map.Entry<Integer, Integer> leaveEntry : groupLeaveHashMap.entrySet()) {
int group = leaveEntry.getKey();
int leaveSize = leaveEntry.getValue();
groupPresentHashMap.put(group,groupPresentHashMap.get(group)-leaveSize);
}
}
//如果只有一个人,从一个组换到另一个组,之前的数据没有清空,需要先进行清空,置空为0
SharedUtil.getInstance(this).writeShared(WATERPROOF,0);
SharedUtil.getInstance(this).writeShared(OUTRIGGER,0);
SharedUtil.getInstance(this).writeShared(BUILD,0);
SharedUtil.getInstance(this).writeShared(SUPERVISOR,0);
for (Map.Entry<Integer, Integer> presentEntry : groupPresentHashMap.entrySet()) {
int group = presentEntry.getKey();
int presentSize = presentEntry.getValue();
Log.i(TAG, "updatePresentSize: group="+group+",presentSize="+presentSize);
switch (group){
case WATERPROOF_ID:
SharedUtil.getInstance(this).writeShared(WATERPROOF,presentSize);
break;
case OUTRIGGER_ID:
SharedUtil.getInstance(this).writeShared(OUTRIGGER,presentSize);
break;
case BUILD_ID:
SharedUtil.getInstance(this).writeShared(BUILD,presentSize);
break;
case SUPERVISOR_ID:
SharedUtil.getInstance(this).writeShared(SUPERVISOR,presentSize);
break;
}
}
ArrayList<GroupBean> groupBeans = updateGroup();
if (groupAdapter != null) {
groupAdapter.setDataList(groupBeans);
}
}
@Override
public void onQueryStatus(String desc, boolean status) {
runOnUiThread(()->{
if (!status){
showTips(desc);
}
});
}
@Override
public void getTotalPerson(List<PersonEntity> personEntities,int type) {
/*Log.i(TAG, "getTotalPerson: size="+personEntities.size());
for (PersonEntity personEntity : personEntities) {
Log.i(TAG, "getTotalPerson: personName="+personEntity.getPerson_name());
}*/
Log.i(TAG, "getTotalPerson: 已获取总数:personEntities.size="+personEntities.size());
PersonMgr.getInstance().updatePersonThread(personEntities, () -> {
runOnUiThread(()->{
ClickUtil.enableClick(mBinding.btnGroupDetail);
});
Intent intent = new Intent(MainActivity.this, GroupActivity.class);
startActivity(intent);
});
}
@Override
public void OnIPChange(String ipAddress, String networkType) {
Log.i(TAG, "OnIPChange: change==>");
//questApi();
/*List<ConfigBean> enterConfigList = SharedUtil.getInstance(this).readSharedList(ENTER_TYPE, ConfigBean.class, "");
ApiQuest.startEnterApi(enterConfigList,this);
List<ConfigBean> leaveConfigList = SharedUtil.getInstance(this).readSharedList(LEAVE_TYPE, ConfigBean.class, "");
ApiQuest.startLeaveApi(leaveConfigList,this);*/
List<ConfigEntity> enterConfigList = ConfigHelper.getInstance().queryByType(ENTER_TYPE);
ApiQuest.getInstance().startApi(enterConfigList,ENTER_TYPE);
ApiQuest.getInstance().setOnUpperDevicesCallback(this);
List<ConfigEntity> leaveConfigList = ConfigHelper.getInstance().queryByType(LEAVE_TYPE);
ApiQuest.getInstance().startApi(leaveConfigList,LEAVE_TYPE);
ApiQuest.getInstance().setOnUpperDevicesCallback(this);
}
@Override
public void OnIPLost(String error) {
ApiQuest.getInstance().stopApi();
}
@Override
public void onUpdateConfig(List<ConfigEntity> configList, int type) {
//配置改变,更新接口
//Log.i(TAG, "onUpdateConfig: config="+configBean.toString()+",type="+type);
/*if (type==ENTER_TYPE){
ApiQuest.getInstance().startEnterApi(configList);
}else if (type == LEAVE_TYPE){
ApiQuest.getInstance().startLeaveApi(configList);
}*/
/*for (ConfigEntity config : configList) {
Log.i(TAG, "onUpdateConfig: pass="+config.getPassword());
Log.i(TAG, "onUpdateConfig: ip="+config.getServerIp());
}*/
ApiQuest.getInstance().startApi(configList,type);
ApiQuest.getInstance().setOnUpperDevicesCallback(this);
}
@Override
public void getAllPassInfo(List<PersonEntity> passAllEntities, int type) {
runOnUiThread(()->{
updatePassInfo(passAllEntities, type);
});
}
@Override
public void onAllConnectStatus(boolean hasConnect, int type) {
Log.i(TAG, "onAllConnectStatus: 接收到的连接状态 hasConnect="+hasConnect);
runOnUiThread(()->{
if (type==ENTER_TYPE){
if (!hasConnect) {
mBinding.tvEnterError.setVisibility(View.VISIBLE);
}else{
mBinding.tvEnterError.setVisibility(View.GONE);
}
}else if (type == LEAVE_TYPE){
if (!hasConnect) {
mBinding.tvLeaveError.setVisibility(View.VISIBLE);
}else{
mBinding.tvLeaveError.setVisibility(View.GONE);
}
}
});
}
}
\ No newline at end of file
package com.srthinker.statinfo.uis;
import android.app.Application;
import com.raizlabs.android.dbflow.config.FlowManager;
public class MyApplication extends Application {
private static MyApplication application;
// 1秒钟后重启应用
private int time = 1000;
@Override
public void onCreate() {
super.onCreate();
application = this;
FlowManager.init(this);
// 程序崩溃时触发线程 以下用来捕获程序崩溃异常
//Thread.setDefaultUncaughtExceptionHandler(handler);
}
public static MyApplication getInstance(){
return application;
}
/*private Thread.UncaughtExceptionHandler handler = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
restartApp(); //发生崩溃异常时,重启应用
}
};
@SuppressLint("WrongConstant")
private void restartApp() {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(
application.getApplicationContext(), 0, intent, FLAG_ACTIVITY_NEW_TASK);
//退出程序
AlarmManager mgr = (AlarmManager) application.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + time,
restartIntent);
//结束进程之前可以把你程序的注销或者退出代码放在这段代码之前
android.os.Process.killProcess(android.os.Process.myPid());
}*/
}
package com.srthinker.statinfo.uis.fragment;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public abstract class BaseFragment extends Fragment {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initData();
initView();
}
protected abstract void initData();
protected abstract void initView();
public void showTips(String tips){
getActivity().runOnUiThread(()->{
Toast.makeText(getContext(), tips, Toast.LENGTH_SHORT).show();
});
}
}
package com.srthinker.statinfo.uis.fragment;
import static com.srthinker.statinfo.constant.InOutType.ENTER_TYPE;
import static com.srthinker.statinfo.constant.InOutType.LEAVE_TYPE;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.InputType;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import com.srthinker.statinfo.database.helper.ConfigHelper;
import com.srthinker.statinfo.databinding.DialogConfigBinding;
import com.srthinker.statinfo.listener.ConfigCallback;
import com.srthinker.statinfo.util.common.Utils;
import com.srthinker.statinfo.wedget.EditView;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ConfigDlgFragment extends DialogFragment {
private static final String TAG = "ConfigDlgFragment";
private Context context;
private int type;
private com.srthinker.statinfo.databinding.DialogConfigBinding mBinding;
//private List<ConfigBean> mLastConfig;
private ConfigCallback callback;
private String mLastAccount;
private String mLastPassword;
//private String mLastServerIp;
private String username;
private List<EditView> devicesIpList = new ArrayList<>();
private List<ConfigEntity> mLastConfig;
private boolean isUpdate = false;
//private List<String> mLastServerIpList = new ArrayList<>();
public static ConfigDlgFragment getInstance(int type){
ConfigDlgFragment configDlgFragment = new ConfigDlgFragment();
Bundle bundle = new Bundle();
bundle.putInt("type",type);
configDlgFragment.setArguments(bundle);
return configDlgFragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
context = getContext();
if (getArguments() != null) {
type = getArguments().getInt("type");
}
mBinding = DialogConfigBinding.inflate(inflater, container, false);
initData();
initView();
return mBinding.getRoot();
}
private void initView() {
mBinding.evAccount.initItem("设备账号:","输入设备账号");
mBinding.evPassword.initItem("设备密码:","输入设备密码");
mBinding.evServerip.initItem("设备1的IP:","输入设备1的IP");
devicesIpList.add(mBinding.evServerip);
mBinding.evPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
if (type== ENTER_TYPE){
mBinding.tvTitle.setText("进去设备的配置信息");
}else if (type == LEAVE_TYPE){
mBinding.tvTitle.setText("离开设备的配置信息");
}
if (!TextUtils.isEmpty(mLastAccount)){
mBinding.evAccount.setContent(mLastAccount);
}else{
if (!TextUtils.isEmpty(username)){
mBinding.evAccount.setContent(username);
}
}
if (!TextUtils.isEmpty(mLastPassword)){
mBinding.evPassword.setContent(mLastPassword);
}
/*if (!TextUtils.isEmpty(mLastServerIp)){
mBinding.evServerip.setContent(mLastServerIp);
}*/
//如果有存储的,显示存储的ip
if (mLastConfig != null) {
for (int i = 0; i < mLastConfig.size(); i++) {
ConfigEntity config = mLastConfig.get(i);
if (config != null) {
String serverIp = config.getServerIp();
boolean connect = config.isConnect();
if (i==0){
mBinding.evServerip.setContent(serverIp);
mBinding.evServerip.setStatus(connect);
}else{
addDeviceIpView();
EditView editView = devicesIpList.get(i);
editView.setContent(serverIp);
editView.setStatus(connect);
}
}
}
}
mBinding.ivClose.setOnClickListener(v->{
dismiss();
});
mBinding.btnCancel.setOnClickListener(v->{
dismiss();
});
mBinding.btnConfirm.setOnClickListener(v->{
updateConfig();
});
mBinding.tvAddNewIp.setOnClickListener(v->{
addDeviceIpView();
});
}
private void updateConfig() {
String account = mBinding.evAccount.getContent();
String password = mBinding.evPassword.getContent();
String serverIp = mBinding.evServerip.getContent();
if (TextUtils.isEmpty(account)){
Utils.showTips(context,"请输入账号名!");
return;
}
if (TextUtils.isEmpty(password)){
Utils.showTips(context,"请输入密码!");
return;
}
/*if (TextUtils.isEmpty(serverIp)){
Utils.showTips(context,"请输入IP!");
return;
}*/
if (!checkAtLeastOneIp()){
Utils.showTips(context,"请输入IP!");
return;
}
//List<ConfigBean> configBeanList = new ArrayList<>();
List<ConfigEntity> configEntities = new ArrayList<>();
List<String> allDeviceIps = getAllDeviceIps();
/*for (String deviceIp : allDeviceIps) {
ConfigBean configBean = new ConfigBean(account, password, deviceIp);
configBeanList.add(configBean);
}*/
for (int i = 0; i < allDeviceIps.size(); i++) {
String ip = allDeviceIps.get(i);
ConfigEntity config = new ConfigEntity();
config.setUsername(account);
config.setPassword(password);
config.setServerIp(ip);
config.setType(type);
if (mLastConfig != null&&mLastConfig.size()>i) {
ConfigEntity mLastEntity = mLastConfig.get(i);
if (TextUtils.equals(mLastEntity.getServerIp(),ip)){
config.setId(mLastEntity.getId());
config.setConnect(mLastEntity.isConnect());
}
/*try {
String newConfigString = GsonUtil.toJsonString(config);
String lastConfigString = GsonUtil.toJsonString(mLastEntity);
Log.i(TAG, "updateConfig: newConfigString="+newConfigString);
Log.i(TAG, "updateConfig: lastConfigString="+lastConfigString);
if (!TextUtils.equals(newConfigString,lastConfigString)){
isUpdate = true;
}
} catch (Exception e) {
e.printStackTrace();
}*/
}
configEntities.add(config);
}
/*Log.i(TAG, "updateConfig: mLastConfig="+ GsonUtil.ListToJson(mLastConfig));
Log.i(TAG, "updateConfig: configEntity="+GsonUtil.ListToJson(configEntities));*/
if (mLastConfig!=null&&!mLastConfig.equals(configEntities)){
/*if (callback != null) {
SharedUtil.getInstance(context).writeShared(type,configBeanList);
callback.onUpdateConfig(configBeanList,type);
Utils.showTips(context,"已更新配置");
}*/
if (callback != null) {
ConfigHelper.getInstance().delete(mLastConfig);
ConfigHelper.getInstance().add(configEntities);
callback.onUpdateConfig(configEntities,type);
Utils.showTips(context,"已更新配置");
}
}
dismiss();
}
/*private void initData() {
mLastConfig = SharedUtil.getInstance(context).readSharedList(type, ConfigBean.class, "");
if (mLastConfig!=null){
for (int i = 0; i < mLastConfig.size(); i++) {
ConfigBean configBean = mLastConfig.get(i);
if (configBean != null) {
if (i==0){
mLastAccount = configBean.getUsername();
mLastPassword = configBean.getPassword();
}
}
}
}
}*/
private void initData(){
mLastConfig = ConfigHelper.getInstance().queryByType(type);
if (this.mLastConfig !=null){
for (int i = 0; i < this.mLastConfig.size(); i++) {
ConfigEntity config = this.mLastConfig.get(i);
if (config != null) {
if (i==0){
mLastAccount = config.getUsername();
mLastPassword = config.getPassword();
}
}
}
}
}
public void setUsername(String username){
this.username = username;
}
//获取所有设备ip
private List<String> getAllDeviceIps(){
List<String> ips = new ArrayList<>();
for (EditView editView : devicesIpList) {
String ip = editView.getContent();
if (!TextUtils.isEmpty(ip)){
ips.add(ip);
}
}
//去重,保证没有重复的Ip
ips=ips.stream()
.distinct()
.collect(Collectors.toList());
return ips;
}
//检查至少一个ip不为空
private boolean checkAtLeastOneIp(){
for (EditView editView : devicesIpList) {
String ip = editView.getContent();
if (!TextUtils.isEmpty(ip)){
return true;
}
}
return false;
}
private void addDeviceIpView(){
EditView editView = new EditView(context,null);
int number = devicesIpList.size() + 1;
editView.initItem("设备"+number+"的IP:","输入设备"+number+"的IP");
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
editView.setLayoutParams(layoutParams);
mBinding.llIps.addView(editView);
devicesIpList.add(editView);
}
@Override
public void onResume() {
super.onResume();
initWindow();
}
private void initWindow() {
Window window = getDialog().getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setLayout(Utils.dip2px(context,280),ViewGroup.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mBinding = null;
}
public void setConfigCallback(ConfigCallback callback){
this.callback = callback;
}
}
package com.srthinker.statinfo.uis.fragment;
import static com.srthinker.statinfo.constant.GroupConst.GROUPED;
import static com.srthinker.statinfo.constant.GroupConst.NO_GROUP;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.database.PersonMgr;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.databinding.FragmentGroupBinding;
import com.srthinker.statinfo.uis.fragment.group.GroupedFragment;
import com.srthinker.statinfo.uis.fragment.group.NoGroupFragment;
import com.srthinker.statinfo.uis.fragment.group.SelectDlgFragment;
import java.util.List;
public class GroupFragment extends BaseFragment{
private static final String TAG = "GroupFragment";
private com.srthinker.statinfo.databinding.FragmentGroupBinding mBinding;
private Context mContext;
private FragmentActivity mActivity;
private NoGroupFragment noGroupFragment;
private GroupedFragment groupedFragment;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mContext = getContext();
mActivity = getActivity();
mBinding = FragmentGroupBinding.inflate(inflater, container, false);
return mBinding.getRoot();
}
@Override
protected void initData() {
/*noGroupFragment = new NoGroupFragment();
groupedFragment = new GroupedFragment();*/
}
@Override
protected void initView() {
selectPage(NO_GROUP);
mBinding.tvTabNo.setOnClickListener(v-> selectPage(NO_GROUP));
mBinding.tvTabYes.setOnClickListener(v-> selectPage(GROUPED));
mBinding.ivBack.setOnClickListener(v-> mActivity.onBackPressed());
mBinding.btnGrouping.setOnClickListener(v-> clickGrouping());
mBinding.btnRemove.setOnClickListener(v-> clickRemove());
}
private void clickRemove() {
if (groupedFragment != null) {
List<PersonEntity> selectItems = groupedFragment.getSelectItemsCurrent();
if (selectItems==null||selectItems.size()<=0){
showTips("请先选择要移除的人员");
return;
}
for (PersonEntity selectItem : selectItems) {
selectItem.setGroup(0);
}
PersonMgr.getInstance().updateFromListThread(selectItems, () -> {
groupedFragment.updateListCurrent();
showTips("移除成功!");
});
}
}
private void clickGrouping() {
if (noGroupFragment != null) {
List<PersonEntity> noGroupSelects = noGroupFragment.getSelectedItems();
if (noGroupSelects==null||noGroupSelects.size()<=0){
showTips("请先选择要分组人员");
return;
}
SelectDlgFragment selectDlgFragment = SelectDlgFragment.getInstance();
if (selectDlgFragment.isResumed()){
return;
}
selectDlgFragment.showNow(mActivity.getSupportFragmentManager(),SelectDlgFragment.class.getSimpleName());
selectDlgFragment.setCancelable(false);
selectDlgFragment.setOnSelectOneListener(select -> {
//Log.i(TAG, "initView: select="+select);
for (PersonEntity noGroupSelect : noGroupSelects) {
noGroupSelect.setGroup(select);
}
PersonMgr.getInstance().updateFromListThread(noGroupSelects, () -> {
noGroupFragment.updateNoList();
showTips("已更新列表");
});
});
}
}
private void selectPage(int page) {
switch (page){
case NO_GROUP:
mBinding.tvTabNo.setSelected(true);
mBinding.tvTabYes.setSelected(false);
mBinding.btnGrouping.setVisibility(View.VISIBLE);
mBinding.btnRemove.setVisibility(View.GONE);
noGroupFragment = new NoGroupFragment();
getChildFragmentManager().beginTransaction().replace(R.id.fcv_group_people,noGroupFragment,NoGroupFragment.class.getSimpleName())
.commitAllowingStateLoss();
break;
case GROUPED:
mBinding.tvTabYes.setSelected(true);
mBinding.tvTabNo.setSelected(false);
mBinding.btnRemove.setVisibility(View.VISIBLE);
mBinding.btnGrouping.setVisibility(View.GONE);
groupedFragment = new GroupedFragment();
getChildFragmentManager().beginTransaction().replace(R.id.fcv_group_people,groupedFragment,GroupedFragment.class.getSimpleName())
.commitAllowingStateLoss();
break;
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
mBinding = null;
}
}
package com.srthinker.statinfo.uis.fragment.group;
import static com.srthinker.statinfo.constant.GroupConst.BUILD_ID;
import static com.srthinker.statinfo.constant.GroupConst.OUTRIGGER_ID;
import static com.srthinker.statinfo.constant.GroupConst.SUPERVISOR_ID;
import static com.srthinker.statinfo.constant.GroupConst.WATERPROOF_ID;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.adapter.GroupPagerAdapter;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.databinding.FragmentGroupedBinding;
import com.srthinker.statinfo.uis.fragment.BaseFragment;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
public class GroupedFragment extends BaseFragment {
private static final String TAG = "GroupedFragment";
private com.srthinker.statinfo.databinding.FragmentGroupedBinding mBinding;
private Context context;
private LinkedHashMap<String, Integer> mGroupMap;
private GroupPagerAdapter groupPagerAdapter;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
context = getContext();
mBinding = FragmentGroupedBinding.inflate(inflater, container, false);
return mBinding.getRoot();
}
@Override
protected void initData() {
mGroupMap = new LinkedHashMap<>();
mGroupMap.put(getString(R.string.select_one), WATERPROOF_ID);
mGroupMap.put(getString(R.string.select_two), OUTRIGGER_ID);
mGroupMap.put(getString(R.string.select_three),BUILD_ID);
mGroupMap.put(getString(R.string.select_four),SUPERVISOR_ID);
}
@Override
protected void initView() {
groupPagerAdapter = new GroupPagerAdapter(getChildFragmentManager(), mGroupMap);
mBinding.vpPager.setAdapter(groupPagerAdapter);
mBinding.tabLayoutGroups.setupWithViewPager(mBinding.vpPager);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mBinding = null;
}
public List<PersonEntity> getSelectItemsCurrent(){
List<PersonEntity> getSelectItems = new ArrayList<>();
//获取当前分组勾选的数据
int currentItem = mBinding.vpPager.getCurrentItem();
Log.i(TAG, "getSelectItems: currentItem="+currentItem);
if (groupPagerAdapter != null) {
TabGroupFragment tabGroupFragment = (TabGroupFragment) groupPagerAdapter.getItem(currentItem);
getSelectItems = tabGroupFragment.getPersonItems();
Log.i(TAG, "getSelectItems: getSelectItems.size="+getSelectItems.size());
}
return getSelectItems;
}
public List<PersonEntity> getSelectItemsTotal(){
List<PersonEntity> getSelectItems = new ArrayList<>();
//获取所有被勾选的数据
if (groupPagerAdapter != null) {
int totalPage = groupPagerAdapter.getCount();
for (int i = 0; i < totalPage; i++) {
TabGroupFragment tabGroupFragment = (TabGroupFragment) groupPagerAdapter.getItem(i);
getSelectItems.addAll(tabGroupFragment.getPersonItems());
}
Log.i(TAG, "getSelectItemsTotal: getSelectItems.size="+getSelectItems.size());
}
return getSelectItems;
}
public void updateListCurrent(){
int currentItem = mBinding.vpPager.getCurrentItem();
if (groupPagerAdapter != null) {
TabGroupFragment tabGroupFragment = (TabGroupFragment) groupPagerAdapter.getItem(currentItem);
tabGroupFragment.updateLists();
}
}
public void updateListTotal(){
if (groupPagerAdapter != null) {
int totalPage = groupPagerAdapter.getCount();
for (int i = 0; i < totalPage; i++) {
TabGroupFragment tabGroupFragment = (TabGroupFragment) groupPagerAdapter.getItem(i);
tabGroupFragment.updateLists();
}
}
}
}
package com.srthinker.statinfo.uis.fragment.group;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.adapter.PersonGroupSAdapter;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.helper.PersonHelper;
import com.srthinker.statinfo.databinding.FragmentNoGroupBinding;
import com.srthinker.statinfo.uis.fragment.BaseFragment;
import java.util.ArrayList;
import java.util.List;
public class NoGroupFragment extends BaseFragment {
private com.srthinker.statinfo.databinding.FragmentNoGroupBinding mBinding;
private List<PersonEntity> noGroupList;
private Context mContext;
private PersonGroupSAdapter mNoGroupAdapter;
private FragmentActivity activity;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mContext = getContext();
activity = getActivity();
mBinding = FragmentNoGroupBinding.inflate(inflater, container, false);
return mBinding.getRoot();
}
@Override
protected void initData() {
noGroupList = new ArrayList<>();
/*for (int i = 0; i < 26; i++) {
PersonEntity entity = new PersonEntity();
entity.setPerson_name("王大锤"+i);
if (i==13){
entity.setPerson_name("当打凄凄切切凄凄切切");
}
noGroupList.add(entity);
}*/
}
@Override
protected void initView() {
//LinearLayoutManager noGroupLLM = new LinearLayoutManager(mContext,LinearLayoutManager.VERTICAL,false);
GridLayoutManager noGroupGLM = new GridLayoutManager(mContext, 12, RecyclerView.HORIZONTAL, false);
mBinding.rvNoGroup.setLayoutManager(noGroupGLM);
mNoGroupAdapter = new PersonGroupSAdapter(mContext, noGroupList);
mBinding.rvNoGroup.setItemAnimator(new DefaultItemAnimator());
mBinding.rvNoGroup.setAdapter(mNoGroupAdapter);
}
@Override
public void onResume() {
super.onResume();
updateNoList();
}
@Override
public void onDestroyView() {
super.onDestroyView();
mBinding = null;
}
public List<PersonEntity> getSelectedItems(){
if (mNoGroupAdapter != null) {
return mNoGroupAdapter.getSelectedItem();
}
return null;
}
public void updateNoList(){
//查询数据库
if (activity != null) {
activity.runOnUiThread(()->{
noGroupList = PersonHelper.getInstance().queryByGroup(0);
if (mNoGroupAdapter != null) {
mNoGroupAdapter.setDataList(noGroupList);
}
});
}
}
}
package com.srthinker.statinfo.uis.fragment.group;
import static com.srthinker.statinfo.constant.GroupConst.BUILD_ID;
import static com.srthinker.statinfo.constant.GroupConst.OUTRIGGER_ID;
import static com.srthinker.statinfo.constant.GroupConst.SUPERVISOR_ID;
import static com.srthinker.statinfo.constant.GroupConst.WATERPROOF_ID;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import com.srthinker.statinfo.R;
import com.srthinker.statinfo.databinding.DialogSelectBinding;
import com.srthinker.statinfo.util.common.Utils;
public class SelectDlgFragment extends DialogFragment {
private static final String TAG = "SelectDlgFragment";
private com.srthinker.statinfo.databinding.DialogSelectBinding mBinding;
private Context context;
private int select = 0;
private OnSelectOneListener onSelectOneListener;
public static SelectDlgFragment getInstance(){
SelectDlgFragment selectDlgFragment = new SelectDlgFragment();
return selectDlgFragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
context = getContext();
mBinding = DialogSelectBinding.inflate(inflater, container, false);
initData();
initView();
return mBinding.getRoot();
}
private void initData() {
}
private void initView() {
mBinding.ivClose.setOnClickListener(v->{
dismiss();
});
mBinding.btnCancel.setOnClickListener(v->{
dismiss();
});
mBinding.btnConfirm.setOnClickListener(v->{
//Log.i(TAG, "initView: select="+select);
if (onSelectOneListener != null) {
onSelectOneListener.onSelectOne(select);
}
//Utils.showTips(context,"已更新列表");
dismiss();
});
mBinding.rgSelect.setOnCheckedChangeListener((radioGroup, i) -> {
switch (i){
case R.id.rb_select_one:
select = WATERPROOF_ID;
break;
case R.id.rb_select_two:
select =OUTRIGGER_ID;
break;
case R.id.rb_select_three:
select = BUILD_ID;
break;
case R.id.rb_select_four:
select = SUPERVISOR_ID;
break;
}
});
}
@Override
public void onResume() {
super.onResume();
initWindow();
}
private void initWindow() {
Window window = getDialog().getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.setLayout(Utils.dip2px(context,395),ViewGroup.LayoutParams.WRAP_CONTENT);
window.setGravity(Gravity.CENTER);
}
@Override
public void onDestroyView() {
super.onDestroyView();
mBinding = null;
}
public void setOnSelectOneListener(OnSelectOneListener onSelectOneListener){
this.onSelectOneListener = onSelectOneListener;
}
public interface OnSelectOneListener{
void onSelectOne(int select);
}
}
package com.srthinker.statinfo.uis.fragment.group;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.srthinker.statinfo.adapter.PersonGroupSAdapter;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.database.helper.PersonHelper;
import com.srthinker.statinfo.databinding.FragmentTabGroupBinding;
import com.srthinker.statinfo.uis.fragment.BaseFragment;
import java.util.ArrayList;
import java.util.List;
public class TabGroupFragment extends BaseFragment {
private static final String TAG = "TabGroupFragment";
private com.srthinker.statinfo.databinding.FragmentTabGroupBinding mBinding;
private Context context;
private int type;
private List<PersonEntity> personItems;
private PersonGroupSAdapter groupSAdapter;
private FragmentActivity activity;
public static TabGroupFragment getInstance(int type){
TabGroupFragment tabGroupFragment = new TabGroupFragment();
Bundle bundle = new Bundle();
bundle.putInt("type",type);
tabGroupFragment.setArguments(bundle);
return tabGroupFragment;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
context = getContext();
activity = getActivity();
if (getArguments() != null) {
type = getArguments().getInt("type");
}
mBinding = FragmentTabGroupBinding.inflate(inflater, container, false);
return mBinding.getRoot();
}
@Override
protected void initData() {
personItems = new ArrayList<>();
/*for (int i = 0; i < 100; i++) {
PersonEntity entity = new PersonEntity();
entity.setPerson_name("赵美丽"+i+"-"+type);
personItems.add(entity);
}*/
personItems = PersonHelper.getInstance().queryByGroup(type);
}
@Override
protected void initView() {
GridLayoutManager groupGLM = new GridLayoutManager(context, 12, RecyclerView.HORIZONTAL,false);
mBinding.rvTabGroup.setLayoutManager(groupGLM);
groupSAdapter = new PersonGroupSAdapter(context, personItems);
mBinding.rvTabGroup.setAdapter(groupSAdapter);
}
@Override
public void onDestroyView() {
//Log.i(TAG, "onDestroyView: 有进行销毁!group类型="+type);
super.onDestroyView();
mBinding = null;
}
public List<PersonEntity> getPersonItems(){
List<PersonEntity> personItems = new ArrayList<>();
if (groupSAdapter!=null){
personItems = groupSAdapter.getSelectedItem();
}
return personItems;
}
public void updateLists(){
if (activity != null) {
activity.runOnUiThread(()->{
//访问数据库,然后刷新
/*//模拟
personItems = new ArrayList<>();
for (int i = 0; i < 100; i++) {
PersonEntity entity = new PersonEntity();
entity.setPerson_name("王大锤"+i+"-"+type);
personItems.add(entity);
}*/
personItems = PersonHelper.getInstance().queryByGroup(type);
if (groupSAdapter != null) {
groupSAdapter.setDataList(personItems);
}
});
}
}
}
package com.srthinker.statinfo.update;
import android.content.Context;
/**
* @author liwanlian
* @date 2023/2/28 16:14
*/
public class AppSpUtil {
/**
* 设备信息
**/
public static EquipmentInfo getEquipmentInfo(Context context) {
return SharedPreferencesUtil.getInstance(context).get("key_dev_info", EquipmentInfo.class);
}
public static void setEquipmentInfo(Context context, EquipmentInfo equipmentInfo) {
SharedPreferencesUtil.getInstance(context).put("key_dev_info", equipmentInfo);
}
/**
* 人证比对阈值
**/
public static Float getIdentityThreshold(Context context) {
return SharedPreferencesUtil.getInstance(context).getFloat("key_identity_threshold", 0.47f);
}
public static void setIdentityThreshold(Context context, Float value) {
SharedPreferencesUtil.getInstance(context).put("key_identity_threshold", value);
}
/**
* 是否使用抓拍比对
**/
public static boolean getUseSnapIdentity(Context context) {
return SharedPreferencesUtil.getInstance(context).getBoolean("key_identity_snap", true);
}
public static void setUseSnapIdentity(Context context, boolean snap) {
SharedPreferencesUtil.getInstance(context).put("key_identity_snap", snap);
}
/**
* 自动比对的限时时间
**/
public static int getAutoIdentityTime(Context context) {
return SharedPreferencesUtil.getInstance(context).getInt("key_identity_time", 6);
}
public static void setAutoIdentityTime(Context context, int time) {
SharedPreferencesUtil.getInstance(context).put("key_identity_time", time);
}
/**
* 设备Sn
*
* @param context
* @return
*/
public static String getDeviceSnCache(Context context) {
return SharedPreferencesUtil.getInstance(context).getString("key_dev_sn");
}
public static void setDeviceSnCache(Context context, String deviceSn) {
SharedPreferencesUtil.getInstance(context).putString("key_dev_sn", deviceSn);
}
}
package com.srthinker.statinfo.update
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.os.Build
import android.text.TextUtils
import android.util.Base64
import android.util.Log
import java.net.Inet4Address
import java.net.NetworkInterface
import java.net.SocketException
import java.text.SimpleDateFormat
import java.util.*
/**
* @Author liwanlian
* @Date 2022/3/7 14:38
*/
public object AppUtils {
// bytearray 转bitmap
@JvmStatic
fun byteToBitmap(b: ByteArray): Bitmap? {
return if (b == null || b.isEmpty()) {
null
} else {
BitmapFactory.decodeByteArray(b, 0, b.size)
}
}
/**
* 获取app的具体版本名(eg:1.0.1)
*
* @param context
* @return
*/
@JvmStatic
fun getVersionName(context: Context): String? {
val manager = context.packageManager
var name = ""
try {
val info = manager.getPackageInfo(context.packageName, 0)
name = info.versionName
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
return name
}
/**
* 比较两版本哪个是最新
*
* @param netVersion 网络检测到的版本
* @param localVersion 系统当前的版本
* @return
*/
fun isBiggerVersion(netVersion: String, localVersion: String): Boolean {
val net = version2Int(netVersion)
val local = version2Int(localVersion)
return local < net
}
private fun version2Int(version: String): Int {
val str = version.replace(".", "")
return str.toInt()
}
/**
* 获取app的具体版本Code
*
* @param context
* @return
*/
fun getVersionCode(context: Context): String? {
val manager = context.packageManager
var versionCode = ""
try {
val info = manager.getPackageInfo(context.packageName, 0)
versionCode = info.versionCode.toString()
} catch (e: PackageManager.NameNotFoundException) {
e.printStackTrace()
}
return versionCode
}
//获取ip地址
fun getIpAddress(context: Context): String? {
val info = (context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
if (info != null && info.isConnected) {
// 3/4g网络
if (info.type == ConnectivityManager.TYPE_MOBILE) {
try {
val en = NetworkInterface.getNetworkInterfaces()
while (en.hasMoreElements()) {
val intf = en.nextElement()
val enumIpAddr = intf.inetAddresses
while (enumIpAddr.hasMoreElements()) {
val inetAddress = enumIpAddr.nextElement()
if (!inetAddress.isLoopbackAddress && inetAddress is Inet4Address) {
return inetAddress.getHostAddress()
}
}
}
} catch (e: SocketException) {
e.printStackTrace()
}
} else if (info.type == ConnectivityManager.TYPE_WIFI) {
// wifi网络
val wifiManager =
context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiInfo = wifiManager.connectionInfo
return intIP2StringIP(wifiInfo.ipAddress)
} else if (info.type == ConnectivityManager.TYPE_ETHERNET) {
// 有限网络
return getLocalIp()
}
}
return null
}
private fun intIP2StringIP(ip: Int): String {
return (ip and 0xFF).toString() + "." +
(ip shr 8 and 0xFF) + "." +
(ip shr 16 and 0xFF) + "." +
(ip shr 24 and 0xFF)
}
// 获取有限网IP
private fun getLocalIp(): String? {
try {
val en = NetworkInterface
.getNetworkInterfaces()
while (en.hasMoreElements()) {
val intf = en.nextElement()
val enumIpAddr = intf
.inetAddresses
while (enumIpAddr.hasMoreElements()) {
val inetAddress = enumIpAddr.nextElement()
if (!inetAddress.isLoopbackAddress
&& inetAddress is Inet4Address
) {
return inetAddress.getHostAddress()
}
}
}
} catch (ex: SocketException) {
}
return "0.0.0.0"
}
/**
* 解码
*
* @param base64String
* @return
*/
fun FromBase64(base64String: String): String? {
try {
return String(Base64.decode(base64String.toByteArray(), Base64.NO_WRAP))
} catch (e: java.lang.Exception) {
e.printStackTrace()
Log.i("FromBase64", "FromBase64" + e.toString())
return ""
}
}
/**
* 判断str1中包含str2的个数
* @param str1
* @param str2
* @return counter
*/
fun formatStrDate(strDate: String): String {
//时间转时间戳
try {
var res = ""
var simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
var date = simpleDateFormat.parse(strDate);
var ts = date.time
res = ts.toString()
Log.i("lwl", "formatStrDate: $strDate $res")
val calendar: Calendar = Calendar.getInstance()
calendar.timeInMillis = ts
Log.i(
"getNetTime",
"formatStrDate: ${calendar.get(Calendar.YEAR)} month:${calendar.get(Calendar.MONTH) + 1} day:${
calendar.get(
Calendar.DAY_OF_MONTH
)
}"
)
var year = calendar.get(Calendar.YEAR)
var month = calendar.get(Calendar.MONTH) + 1
var day = calendar.get(Calendar.DAY_OF_MONTH)
var sb = StringBuffer()
sb.append(year).append("年")
if (month < 10) {
sb.append("0").append(month)
} else {
sb.append(month)
}
sb.append("月")
if (day < 10) {
sb.append("0").append(day)
} else {
sb.append(day)
}
sb.append("日")
Log.i("lwl", "formatStrDate: ${sb.toString()}")
return sb.toString()
} catch (e: Exception) {
e.printStackTrace()
return strDate
}
}
/**
* 获取操作系统
*/
val oS: String
get() {
return "Android" + Build.VERSION.RELEASE
}
fun isEmailValid(email: String): Boolean {
return !TextUtils.isEmpty(email) && android.util.Patterns.EMAIL_ADDRESS.matcher(email)
.matches()
}
}
\ No newline at end of file
package com.srthinker.statinfo.update
import android.content.Context
import android.widget.Toast
import androidx.lifecycle.ViewModel
import com.srthinker.statinfo.uis.MainActivity
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
/**
* @author liwanlian
* @date 2023/4/3 16:28
*/
abstract class BaseViewModel : ViewModel() {
lateinit var mContext: Context
lateinit var mActivity: MainActivity
/**
* 线程任务队列
*/
private val mTaskDispatcherTaskQueue: ResizableCapacityLinkedBlockIngQueue<Runnable> =
ResizableCapacityLinkedBlockIngQueue(1)
val mTaskDispatcherTaskExecutor = ThreadPoolExecutor(
2,
3,
1, TimeUnit.MINUTES,
mTaskDispatcherTaskQueue,
ThreadPoolExecutor.DiscardOldestPolicy()
)
open fun init(context: Context, mainActivity: MainActivity) {
mContext = context
mActivity = mainActivity
}
fun showTips(content: String) {
mActivity.runOnUiThread {
Toast.makeText(mContext, content, Toast.LENGTH_SHORT).show()
}
}
abstract fun releaseRes()
}
\ No newline at end of file
package com.srthinker.statinfo.update;
/**
* @author liwanlian
* 设备信息
* @date 2021/5/13 15:58
*/
public class EquipmentInfo {
/**
* 设备sn
*/
public String sn = "";
/**
* 产品key
*/
public String productKey = "";
/**
* 设备名称
*/
public String deviceName = "";
/**
* 设备秘钥
*/
public String deviceSecret = "";
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getProductKey() {
return productKey;
}
public void setProductKey(String productKey) {
this.productKey = productKey;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getDeviceSecret() {
return deviceSecret;
}
public void setDeviceSecret(String deviceSecret) {
this.deviceSecret = deviceSecret;
}
}
package com.srthinker.statinfo.update;
/**
* @author liwanlian
* @date 2021/5/27 18:58
* 通过设备sn获取设备的一些信息
*/
public class GetDataBySnBean {
/**
* createTime : null
* currentPage : 1
* deleted : 0
* description :
* devModel : T5
* devName : WJYZA7-C2FRM3
* devSn : 34466798
* id : 0
* pageSize : 15
* productKey : 2E1PZO6UWQ8837347
* responseMessageId : 1165294311110082561
* responseTime : 2021-05-27 19:11:46
* secret : c64add462d1b50021d95eaab5e5f56a2
* updateTime : null
*/
private String createTime;
private Integer currentPage;
private Integer deleted;
private String description;
private String devModel;
private String devName;
private String devSn;
private Integer id;
private Integer pageSize;
private String productKey;
private String responseMessageId;
private String responseTime;
private String secret;
private String updateTime;
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public Integer getCurrentPage() {
return currentPage;
}
public void setCurrentPage(Integer currentPage) {
this.currentPage = currentPage;
}
public Integer getDeleted() {
return deleted;
}
public void setDeleted(Integer deleted) {
this.deleted = deleted;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDevModel() {
return devModel;
}
public void setDevModel(String devModel) {
this.devModel = devModel;
}
public String getDevName() {
return devName;
}
public void setDevName(String devName) {
this.devName = devName;
}
public String getDevSn() {
return devSn;
}
public void setDevSn(String devSn) {
this.devSn = devSn;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public String getProductKey() {
return productKey;
}
public void setProductKey(String productKey) {
this.productKey = productKey;
}
public String getResponseMessageId() {
return responseMessageId;
}
public void setResponseMessageId(String responseMessageId) {
this.responseMessageId = responseMessageId;
}
public String getResponseTime() {
return responseTime;
}
public void setResponseTime(String responseTime) {
this.responseTime = responseTime;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public String getUpdateTime() {
return updateTime;
}
public void setUpdateTime(String updateTime) {
this.updateTime = updateTime;
}
}
package com.srthinker.statinfo.update
import android.text.TextUtils
import android.util.Log
import com.srthinker.generaltool.models.RequestConfig
import com.srthinker.generaltool.outside.BaseNetImpl
import com.srthinker.generaltool.outside.NetConstants
import com.srthinker.generaltool.utils.*
import com.srthinker.statinfo.uis.MyApplication
import com.srthinker.statinfo.update.AppUtils.getVersionName
import com.srthinker.statinfo.update.request.BaseReqData
import com.srthinker.statinfo.update.request.GetDeviceInfoBySnReq
import com.srthinker.statinfo.update.request.GetPlatformTokenReq
import com.srthinker.statinfo.update.request.GetVersionFromPlatformReq
import com.srthinker.statinfo.update.response.GetPlatformTokenResp
import com.srthinker.statinfo.update.response.GetVersionFromPlatformResp
/**
* @author liwanlian
* @date 2023/3/6 16:19
*/
class InsideNetImpl : BaseNetImpl() {
private var mqttUrl: String? = null
private var baseUrl: String? = null
private var platFormToken: String? = null
override fun initData() {
if (baseConfig != null) {
mqttUrl = baseConfig.mqttUrl
baseUrl = baseConfig.baseUrl
}
}
/**
* 获取设备信息
*
* @param baseReqData
*/
fun getDevInfoBySn(baseReqData: BaseReqData<GetDeviceInfoBySnReq?>?): Boolean {
return if (baseReqData != null && baseReqData.requestData != null) {
var result = BooleanArray(1)
var equipmentInfo = baseReqData.requestData!!.equipmentInfo
if (equipmentInfo != null && !TextUtils.isEmpty(equipmentInfo.deviceName)) {
Log.i(TAG, "had device info")
result[0] = true
return result[0]
}
var getDeviceInfoBySnReq = baseReqData.requestData
var reqJson = JsonUtil.getJsonString(getDeviceInfoBySnReq)
LogUtil.logDebug("getDevInfoBySn json:\r\n$reqJson")
var requestParams = getRequestRequestParams(
RequestConfig(
GeneralConstants.NetRequestFormat.SynchronousRequest.netFormat,
GeneralConstants.NetRequestType.NormalRequest.getNetType(),
mqttUrl,
URL_GET_DEVICE_INFO,
"application/json",
GeneralConstants.NetRequestType.PostRequest.getNetType(),
reqJson,
HashMap(0),
HashMap(0)
)
)
var netBaseResp = netRequestEntrySync(
null,
requestParams.apiConfig,
requestParams.requestContent,
requestParams.extraConfig
)
result[0] = processDataException(
GeneralConstants.CodeType.Type_String.type,
NetConstants.OPERATE_TYPE_GET_DEVINFO,
netBaseResp,
null,
result[0],
baseReqData.isNeedCallBack
)
LogUtil.logError(
TAG,
"getDevInfoBySn result==>" + result[0]
)
result[0]
} else {
false
}
}
/**
* 获取token
*
* @param baseReqData
* @return
*/
fun getDevToken(baseReqData: BaseReqData<GetPlatformTokenReq?>?): Boolean {
return if (baseReqData != null && baseReqData.requestData != null) {
var hasDevInfo = false
var equipmentInfo = baseReqData.requestData!!.equipmentInfo
if (equipmentInfo != null && !TextUtils.isEmpty(equipmentInfo.deviceName)) {
hasDevInfo = true
} else {
var getDeviceInfoBySnReq = GetDeviceInfoBySnReq()
getDeviceInfoBySnReq.devSn = baseReqData.requestData!!.devSn
var getDeviceInfoBySnReqBaseReqData = BaseReqData<GetDeviceInfoBySnReq?>()
getDeviceInfoBySnReqBaseReqData.requestData = getDeviceInfoBySnReq
getDeviceInfoBySnReqBaseReqData.isNeedCallBack = true
if (getDevInfoBySn(getDeviceInfoBySnReqBaseReqData)) {
hasDevInfo = true
}
}
if (hasDevInfo) {
var getPlatformTokenReq = baseReqData.requestData
getPlatformTokenReq!!.devSn = ""
LogUtil.logInfo(
TAG,
"PRODUCT_KEY==>" + GeneralConstants.PRODUCT_KEY + " DEVICE_NAME==> " + GeneralConstants.DEVICE_NAME +
" PRODUCT_SECRET==> " + GeneralConstants.PRODUCT_SECRET
)
var cid =
GeneralConstants.PRODUCT_KEY + "." + GeneralConstants.DEVICE_NAME
getPlatformTokenReq.clientId = cid
getPlatformTokenReq.deviceName =
GeneralConstants.DEVICE_NAME
getPlatformTokenReq.productKey =
GeneralConstants.PRODUCT_KEY
getPlatformTokenReq.signmethod = "hmacsha1"
var time = (System.currentTimeMillis() / 1000).toString()
getPlatformTokenReq.timestamp = time
var sb = StringBuffer()
sb.append("clientId").append(cid).append("deviceName")
.append(GeneralConstants.DEVICE_NAME)
.append("productKey")
.append(GeneralConstants.PRODUCT_KEY)
.append("timestamp").append(time)
LogUtil.logInfo(
TAG,
"sb content: $sb"
)
var b = NetGeneralTool.hmacSha1Raw(
sb.toString(),
GeneralConstants.PRODUCT_SECRET
)
var sign = DataUtils.getHexString(b, 0, b.size, false)
getPlatformTokenReq.sign = sign
var json = JsonUtil.getJsonString(getPlatformTokenReq)
LogUtil.logInfo(
TAG,
"get platform token req json$json"
)
// CountDownLatch countDownLatch = new CountDownLatch(1);
var result = BooleanArray(1)
var requestParams = getRequestRequestParams(
RequestConfig(
GeneralConstants.NetRequestFormat.SynchronousRequest.netFormat,
GeneralConstants.NetRequestType.NormalRequest.getNetType(),
baseUrl,
URL_GET_PLATFORM_TOKEN,
"application/json",
GeneralConstants.NetRequestType.PostRequest.getNetType(),
json,
HashMap(0),
HashMap(0)
)
)
var netBaseResp = netRequestEntrySync(
null,
requestParams.apiConfig,
requestParams.requestContent,
requestParams.extraConfig
)
result[0] = processDataException(
GeneralConstants.CodeType.Type_Double.type,
NetConstants.OPERATE_TYPE_GET_TOKEN,
netBaseResp,
null,
result[0],
baseReqData.isNeedCallBack
)
LogUtil.logError(
TAG,
"getDevToken result==>" + result[0]
)
result[0]
} else {
false
}
} else {
false
}
}
/**
* 获取版本信息
*
* @param baseReqData
*/
fun getLatestVersion(baseReqData: BaseReqData<GetVersionFromPlatformReq>) {
if (baseReqData != null && baseReqData.requestData != null) {
var hasToken = false
if (!TextUtils.isEmpty(platFormToken)) {
hasToken = true
} else {
var getPlatformTokenReq = GetPlatformTokenReq()
getPlatformTokenReq.devSn = baseReqData.requestData!!.deviceSn
getPlatformTokenReq.version = getVersionName(mContext)
getPlatformTokenReq.equipmentInfo =
AppSpUtil.getEquipmentInfo(MyApplication.getInstance())
var getPlatformTokenReqBaseReqData = BaseReqData<GetPlatformTokenReq?>()
getPlatformTokenReqBaseReqData.requestData = getPlatformTokenReq
if (getDevToken(getPlatformTokenReqBaseReqData)) {
hasToken = true
}
}
if (hasToken) {
var jsonString = JsonUtil.getJsonString(baseReqData.requestData)
LogUtil.logInfo(TAG, "getLatestVersion jsonString==>$jsonString")
var time = System.currentTimeMillis()
var timestamp = time.toString()
LogUtil.logInfo(TAG, "timestamp:$timestamp")
var sb = StringBuffer()
sb.append("token=").append(platFormToken).append("&&timeStamp=").append(timestamp)
var b = NetGeneralTool.hmacSha1Raw(sb.toString(), GeneralConstants.API_SECRET)
var sign = DataUtils.getHexString(b, 0, b.size, false)
Log.i("yy", "sign==>$sign")
var headers: MutableMap<String, String?> = HashMap()
headers["Authorization"] = platFormToken
headers["Sign"] = sign
headers["TimeStamp"] = timestamp
var requestParams = getRequestRequestParams(
RequestConfig(
GeneralConstants.NetRequestFormat.AsynchronousRequest.netFormat,
GeneralConstants.NetRequestType.NormalRequest.getNetType(),
baseUrl,
URL_GET_VERSION,
"application/json",
GeneralConstants.NetRequestType.PostRequest.getNetType(),
jsonString,
headers,
HashMap(0)
)
)
netRequestEntryAsync(
GeneralConstants.CodeType.Type_Double.type,
NetConstants.OPERATE_TYPE_GET_VERSION,
null,
requestParams.apiConfig,
requestParams.requestContent,
requestParams.extraConfig,
baseReqData.isNeedCallBack
)
} else {
onFail(NetConstants.OPERATE_TYPE_GET_VERSION, "-992", "token为空", true)
}
} else {
if (baseReqData != null && baseReqData.isNeedCallBack) {
onFail(NetConstants.OPERATE_TYPE_GET_VERSION, "-991", "请求体为空", true)
}
}
}
override fun onSuccess(
type: Int,
data: Any,
code: Any,
msg: String,
isNeedOutCallback: Boolean
) {
var respData = data as String
LogUtil.logInfo(TAG, "respData=>$respData")
when (type) {
NetConstants.OPERATE_TYPE_GET_DEVINFO -> {
LogUtil.logInfo(TAG, "get device info success")
try {
var getDataBySnBean = JsonUtil.getObject(respData, GetDataBySnBean::class.java)
var mEquipmentInfo = EquipmentInfo()
if (getDataBySnBean != null) {
mEquipmentInfo.deviceName = getDataBySnBean.devName
mEquipmentInfo.deviceSecret = getDataBySnBean.secret
mEquipmentInfo.productKey = getDataBySnBean.productKey
GeneralConstants.PRODUCT_KEY = mEquipmentInfo.productKey
GeneralConstants.PRODUCT_SECRET = mEquipmentInfo.deviceSecret
GeneralConstants.DEVICE_NAME = mEquipmentInfo.deviceName
LogUtil.logInfo(
TAG,
"getDeviceInfoBySn==>" + mEquipmentInfo.sn + " " + mEquipmentInfo.deviceName + " " + mEquipmentInfo.deviceSecret + " " + mEquipmentInfo.productKey
)
AppSpUtil.setEquipmentInfo(
MyApplication.getInstance(),
mEquipmentInfo
)
}
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onSuccess(
NetConstants.OPERATE_TYPE_GET_DEVINFO,
mEquipmentInfo,
code,
msg
)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
NetConstants.OPERATE_TYPE_GET_TOKEN -> {
LogUtil.logInfo(TAG, "get device token success")
try {
var tokenData = JsonUtil.getObject(respData, GetPlatformTokenResp.DataDTO::class.java)
platFormToken = tokenData.token.access_token
LogUtil.logInfo(TAG, "get device token success==>$platFormToken")
} catch (e: Exception) {
e.printStackTrace()
}
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onSuccess(
NetConstants.OPERATE_TYPE_GET_TOKEN,
platFormToken,
code,
msg
)
}
}
NetConstants.OPERATE_TYPE_GET_VERSION -> {
LogUtil.logInfo(TAG, "get version success==>$respData")
var updateInfo = UpdateInfo()
try {
if (!TextUtils.isEmpty(respData)) {
var versionData =
JsonUtil.getObjectList(respData, GetVersionFromPlatformResp::class.java)
if (versionData != null && versionData.size > 0) {
LogUtil.logInfo(TAG, "平台有记录:" + versionData.size)
updateInfo.description = versionData[0].description
updateInfo.downloadUrl = versionData[0].downloadUrl
updateInfo.name = versionData[0].name
updateInfo.downloadVerify = versionData[0].downloadVerify
}
}
} catch (e: Exception) {
e.printStackTrace()
}
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onSuccess(
NetConstants.OPERATE_TYPE_GET_VERSION,
updateInfo,
code,
msg
)
}
}
else -> {}
}
}
override fun onFail(type: Int, code: Any, msg: String, isNeedOutCallback: Boolean) {
when (type) {
NetConstants.OPERATE_TYPE_GET_DEVINFO -> {
LogUtil.logInfo(TAG, "get device info fail $code $msg")
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onFail(NetConstants.OPERATE_TYPE_GET_DEVINFO, code, msg)
}
}
NetConstants.OPERATE_TYPE_GET_TOKEN -> {
LogUtil.logInfo(TAG, "get device token fail $code $msg")
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onFail(NetConstants.OPERATE_TYPE_GET_TOKEN, code, msg)
}
}
NetConstants.OPERATE_TYPE_GET_VERSION -> {
LogUtil.logInfo(TAG, "get version fail")
if (isNeedOutCallback && upperCallback != null) {
upperCallback.onFail(NetConstants.OPERATE_TYPE_GET_VERSION, code, msg)
}
}
else -> {}
}
}
companion object {
var instance: InsideNetImpl? = null
get() {
if (field == null) {
synchronized(InsideNetImpl::class.java) {
if (field == null) {
field = InsideNetImpl()
}
}
}
return field
}
private set
/**
* 获取设备信息url
*/
private const val URL_GET_DEVICE_INFO = "/sys/dev/product/query/secret"
/**
* 获取平台的token
*/
private const val URL_GET_PLATFORM_TOKEN = "/antiepidemic/dev/access/healthCode/auth"
/**
* 获取版本信息
*/
private const val URL_GET_VERSION =
"/antiepidemic/dev/access/healthCode/hard_version/search_latest"
private const val TAG = "lwl-InsideNetImpl"
}
}
\ No newline at end of file
package com.srthinker.statinfo.update;
/**
* @author liwanlian
* @date 2023/6/2 17:44
*/
public interface MDownloadCallBack {
void checkResult(boolean needUpdate,boolean canInstall ,UpdateInfo onlineInfo);
// void onProcess(int process);
// void onDownloadResult(boolean success,String md5);
}
package com.srthinker.statinfo.update
import android.content.Context
import android.text.TextUtils
import android.util.Log
import com.srthinker.generaltool.outside.NetConstants
import com.srthinker.generaltool.outside.callbacks.UpperCallback
import com.srthinker.generaltool.outside.models.BaseConfig
import com.srthinker.generaltool.utils.MD5Utils
import com.srthinker.statinfo.uis.MainActivity
import com.srthinker.statinfo.update.request.BaseReqData
import com.srthinker.statinfo.update.request.GetVersionFromPlatformReq
import java.io.File
/**
* @author liwanlian
* @date 2023/6/2 17:41
*/
class NetworkViewModel : BaseViewModel(),
UpperCallback {
/**网络操作的**/
var insideNet: InsideNetImpl? = null
var MDownloadCallback: MDownloadCallBack? = null
private val baseUrl = "http://web.antiepidemic.srthinker.com"
private val mqttUrl = "https://iot.srthinker.com"
private val thirdUrl = "http://139.9.78.104:8080/"
private val TAG = "lwl-DownloadViewModel"
override fun init(context: Context, mainActivity: MainActivity) {
super.init(context, mainActivity)
initData()
}
private fun initData() {
val baseConfig = BaseConfig()
baseConfig.baseUrl = baseUrl
baseConfig.mqttUrl = mqttUrl
baseConfig.thirdUrl = thirdUrl
insideNet = InsideNetImpl.instance
insideNet?.baseConfig = baseConfig
insideNet?.setCallBacks(mContext, this)
}
fun setDownloadCallback(MDownloadCallBack: MDownloadCallBack) {
this.MDownloadCallback = MDownloadCallBack
}
fun getLastestVersion(deviceSn: String, deviceTypes: String) {
val runnable = Runnable {
var versionReq = GetVersionFromPlatformReq()
versionReq.deviceSn = deviceSn
versionReq.hardTypeName = deviceTypes
val baseReqData: BaseReqData<GetVersionFromPlatformReq> = BaseReqData()
baseReqData.requestData = versionReq
baseReqData.isNeedCallBack = true
insideNet?.getLatestVersion(baseReqData)
}
mTaskDispatcherTaskExecutor.execute(runnable)
}
var onlineVersion: UpdateInfo? = null
override fun onSuccess(type: Int, respData: Any?, code: Any?, msg: String?) {
when (type) {
NetConstants.OPERATE_TYPE_GET_VERSION -> {
onlineVersion = respData as UpdateInfo
if (onlineVersion != null && !TextUtils.isEmpty(onlineVersion?.name)) {
if (AppUtils.isBiggerVersion(
onlineVersion?.name!!,
AppUtils.getVersionName(mContext)!!
)
) {
Log.i("lll", "need down")
var file = File("/storage/self/primary/PdaReadCard.apk")
var downloadUrl = onlineVersion?.downloadUrl
var md5 = onlineVersion?.downloadVerify
if (file.exists()) {
val lMd5: String =
MD5Utils.getMd5ByFile(file)
if (lMd5 == md5) {
if (MDownloadCallback != null) {
MDownloadCallback?.checkResult(true, true, null)
}
return
}
}
if (!TextUtils.isEmpty(downloadUrl) && !TextUtils.isEmpty(md5)) {
if (MDownloadCallback != null) {
MDownloadCallback?.checkResult(true, false, onlineVersion)
}
} else {
//mActivity?.tipViewShowUtils?.showMessage("版本信息有误,下载失败")
}
} else {
Log.i("lll", "no need down")
if (MDownloadCallback != null) {
MDownloadCallback?.checkResult(true, false, null)
}
}
} else {
if (MDownloadCallback != null) {
MDownloadCallback?.checkResult(true, false, null)
}
Log.i("lll", "no need down11")
}
}
}
}
override fun onFail(type: Int, code: Any?, msg: String?) {
if (type == NetConstants.OPERATE_TYPE_GET_VERSION) {
if (MDownloadCallback != null) {
MDownloadCallback?.checkResult(false, false, null)
}
}
}
override fun releaseRes() {
}
}
\ No newline at end of file
package com.srthinker.statinfo.update;
import java.util.AbstractQueue;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
/**
* An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
* linked nodes.
* This queue orders elements FIFO (first-in-first-out).
* The <em>head</em> of the queue is that element that has been on the
* queue the longest time.
* The <em>tail</em> of the queue is that element that has been on the
* queue the shortest time. New elements
* are inserted at the tail of the queue, and the queue retrieval
* operations obtain elements at the head of the queue.
* Linked queues typically have higher throughput than array-based queues but
* less predictable performance in most concurrent applications.
*
* <p>The optional capacity bound constructor argument serves as a
* way to prevent excessive queue expansion. The capacity, if unspecified,
* is equal to {@link Integer#MAX_VALUE}. Linked nodes are
* dynamically created upon each insertion unless this would bring the
* queue above capacity.
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
* Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* Java Collections Framework</a>.
*
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
public class ResizableCapacityLinkedBlockIngQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = -6903933977591709194L;
/*
* A variant of the "two lock queue" algorithm. The putLock gates
* entry to put (and offer), and has an associated condition for
* waiting puts. Similarly for the takeLock. The "count" field
* that they both rely on is maintained as an atomic to avoid
* needing to get both locks in most cases. Also, to minimize need
* for puts to get takeLock and vice-versa, cascading notifies are
* used. When a put notices that it has enabled at least one take,
* it signals taker. That taker in turn signals others if more
* items have been entered since the signal. And symmetrically for
* takes signalling puts. Operations such as remove(Object) and
* iterators acquire both locks.
*
* Visibility between writers and readers is provided as follows:
*
* Whenever an element is enqueued, the putLock is acquired and
* count updated. A subsequent reader guarantees visibility to the
* enqueued Node by either acquiring the putLock (via fullyLock)
* or by acquiring the takeLock, and then reading n = count.get();
* this gives visibility to the first n items.
*
* To implement weakly consistent iterators, it appears we need to
* keep all Nodes GC-reachable from a predecessor dequeued Node.
* That would cause two problems:
* - allow a rogue Iterator to cause unbounded memory retention
* - cause cross-generational linking of old Nodes to new Nodes if
* a Node was tenured while live, which generational GCs have a
* hard time dealing with, causing repeated major collections.
* However, only non-deleted Nodes need to be reachable from
* dequeued Nodes, and reachability does not necessarily have to
* be of the kind understood by the GC. We use the trick of
* linking a Node that has just been dequeued to itself. Such a
* self-link implicitly means to advance to head.next.
*/
/**
* Linked list node class
*/
static class Node<E> {
E item;
/**
* One of:
* - the real successor Node
* - this Node, meaning the successor is head.next
* - null, meaning there is no successor (this is the last node)
*/
Node<E> next;
Node(E x) { item = x; }
}
/** The capacity bound, or Integer.MAX_VALUE if none */
private volatile int capacity;
/** Current number of elements */
private final AtomicInteger count = new AtomicInteger();
/**
* Head of linked list.
* Invariant: head.item == null
*/
transient Node<E> head;
/**
* Tail of linked list.
* Invariant: last.next == null
*/
private transient Node<E> last;
/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();
/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock();
/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();
/**
* Signals a waiting take. Called only from put/offer (which do not
* otherwise ordinarily lock takeLock.)
*/
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
/**
* Signals a waiting put. Called only from take/poll.
*/
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
/**
* Links node at end of queue.
*
* @param node the node
*/
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = node;
}
/**
* Removes a node from head of queue.
*
* @return the node
*/
private E dequeue() {
// assert takeLock.isHeldByCurrentThread();
// assert head.item == null;
Node<E> h = head;
Node<E> first = h.next;
h.next = h; // help GC
head = first;
E x = first.item;
first.item = null;
return x;
}
/**
* Locks to prevent both puts and takes.
*/
void fullyLock() {
putLock.lock();
takeLock.lock();
}
/**
* Unlocks to allow both puts and takes.
*/
void fullyUnlock() {
takeLock.unlock();
putLock.unlock();
}
// /**
// * Tells whether both locks are held by current thread.
// */
// boolean isFullyLocked() {
// return (putLock.isHeldByCurrentThread() &&
// takeLock.isHeldByCurrentThread());
// }
/**
* Creates a {@code ResizableCapacityLinkedBlockIngQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public ResizableCapacityLinkedBlockIngQueue() {
this(Integer.MAX_VALUE);
}
/**
* Creates a {@code ResizableCapacityLinkedBlockIngQueue} with the given (fixed) capacity.
*
* @param capacity the capacity of this queue
* @throws IllegalArgumentException if {@code capacity} is not greater
* than zero
*/
public ResizableCapacityLinkedBlockIngQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
/**
* Creates a {@code ResizableCapacityLinkedBlockIngQueue} with a capacity of
* {@link Integer#MAX_VALUE}, initially containing the elements of the
* given collection,
* added in traversal order of the collection's iterator.
*
* @param c the collection of elements to initially contain
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public ResizableCapacityLinkedBlockIngQueue(Collection<? extends E> c) {
this(Integer.MAX_VALUE);
final ReentrantLock putLock = this.putLock;
putLock.lock(); // Never contended, but necessary for visibility
try {
int n = 0;
for (E e : c) {
if (e == null)
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
enqueue(new Node<E>(e));
++n;
}
count.set(n);
} finally {
putLock.unlock();
}
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
// this doc comment is overridden to remove the reference to collections
// greater in size than Integer.MAX_VALUE
/**
* Returns the number of elements in this queue.
*
* @return the number of elements in this queue
*/
public int size() {
return count.get();
}
// this doc comment is a modified copy of the inherited doc comment,
// without the reference to unlimited queues.
/**
* Returns the number of additional elements that this queue can ideally
* (in the absence of memory or resource constraints) accept without
* blocking. This is always equal to the initial capacity of this queue
* less the current {@code size} of this queue.
*
* <p>Note that you <em>cannot</em> always tell if an attempt to insert
* an element will succeed by inspecting {@code remainingCapacity}
* because it may be the case that another thread is about to
* insert or remove an element.
*/
public int remainingCapacity() {
return capacity - count.get();
}
/**
* Inserts the specified element at the tail of this queue, waiting if
* necessary for space to become available.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
/*
* Note that count is used in wait guard even though it is
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
* signalled if it ever changes from capacity. Similarly
* for all other uses of count in other wait guards.
*/
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
/**
* Inserts the specified element at the tail of this queue, waiting if
* necessary up to the specified wait time for space to become available.
*
* @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
if (e == null) throw new NullPointerException();
long nanos = unit.toNanos(timeout);
int c = -1;
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
if (nanos <= 0)
return false;
nanos = notFull.awaitNanos(nanos);
}
enqueue(new Node<E>(e));
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return true;
}
/**
* Inserts the specified element at the tail of this queue if it is
* possible to do so immediately without exceeding the queue's capacity,
* returning {@code true} upon success and {@code false} if this queue
* is full.
* When using a capacity-restricted queue, this method is generally
* preferable to method {@link BlockingQueue#add add}, which can fail to
* insert an element only by throwing an exception.
*
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
final AtomicInteger count = this.count;
if (count.get() == capacity)
return false;
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get() < capacity) {
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
}
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
return c >= 0;
}
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
E x = null;
int c = -1;
long nanos = unit.toNanos(timeout);
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
if (nanos <= 0)
return null;
nanos = notEmpty.awaitNanos(nanos);
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
public E poll() {
final AtomicInteger count = this.count;
if (count.get() == 0)
return null;
E x = null;
int c = -1;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
if (count.get() > 0) {
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
}
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}
public E peek() {
if (count.get() == 0)
return null;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
Node<E> first = head.next;
if (first == null)
return null;
else
return first.item;
} finally {
takeLock.unlock();
}
}
/**
* Unlinks interior Node p with predecessor trail.
*/
void unlink(Node<E> p, Node<E> trail) {
// assert isFullyLocked();
// p.next is not changed, to allow iterators that are
// traversing p to maintain their weak-consistency guarantee.
p.item = null;
trail.next = p.next;
if (last == p)
last = trail;
if (count.getAndDecrement() == capacity)
notFull.signal();
}
/**
* Removes a single instance of the specified element from this queue,
* if it is present. More formally, removes an element {@code e} such
* that {@code o.equals(e)}, if this queue contains one or more such
* elements.
* Returns {@code true} if this queue contained the specified element
* (or equivalently, if this queue changed as a result of the call).
*
* @param o element to be removed from this queue, if present
* @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
if (o == null) return false;
fullyLock();
try {
for (Node<E> trail = head, p = trail.next;
p != null;
trail = p, p = p.next) {
if (o.equals(p.item)) {
unlink(p, trail);
return true;
}
}
return false;
} finally {
fullyUnlock();
}
}
/**
* Returns {@code true} if this queue contains the specified element.
* More formally, returns {@code true} if and only if this queue contains
* at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this queue
* @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
if (o == null) return false;
fullyLock();
try {
for (Node<E> p = head.next; p != null; p = p.next)
if (o.equals(p.item))
return true;
return false;
} finally {
fullyUnlock();
}
}
/**
* Returns an array containing all of the elements in this queue, in
* proper sequence.
*
* <p>The returned array will be "safe" in that no references to it are
* maintained by this queue. (In other words, this method must allocate
* a new array). The caller is thus free to modify the returned array.
*
* <p>This method acts as bridge between array-based and collection-based
* APIs.
*
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
fullyLock();
try {
int size = count.get();
Object[] a = new Object[size];
int k = 0;
for (Node<E> p = head.next; p != null; p = p.next)
a[k++] = p.item;
return a;
} finally {
fullyUnlock();
}
}
/**
* Returns an array containing all of the elements in this queue, in
* proper sequence; the runtime type of the returned array is that of
* the specified array. If the queue fits in the specified array, it
* is returned therein. Otherwise, a new array is allocated with the
* runtime type of the specified array and the size of this queue.
*
* <p>If this queue fits in the specified array with room to spare
* (i.e., the array has more elements than this queue), the element in
* the array immediately following the end of the queue is set to
* {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose {@code x} is a queue known to contain only strings.
* The following code can be used to dump the queue into a newly
* allocated array of {@code String}:
*
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
* Note that {@code toArray(new Object[0])} is identical in function to
* {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
* same runtime type is allocated for this purpose
* @return an array containing all of the elements in this queue
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this queue
* @throws NullPointerException if the specified array is null
*/
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
fullyLock();
try {
int size = count.get();
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance
(a.getClass().getComponentType(), size);
int k = 0;
for (Node<E> p = head.next; p != null; p = p.next)
a[k++] = (T)p.item;
if (a.length > k)
a[k] = null;
return a;
} finally {
fullyUnlock();
}
}
public String toString() {
fullyLock();
try {
Node<E> p = head.next;
if (p == null)
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = p.item;
sb.append(e == this ? "(this Collection)" : e);
p = p.next;
if (p == null)
return sb.append(']').toString();
sb.append(',').append(' ');
}
} finally {
fullyUnlock();
}
}
/**
* Atomically removes all of the elements from this queue.
* The queue will be empty after this call returns.
*/
public void clear() {
fullyLock();
try {
for (Node<E> p, h = head; (p = h.next) != null; h = p) {
h.next = h;
p.item = null;
}
head = last;
// assert head.item == null && head.next == null;
if (count.getAndSet(0) == capacity)
notFull.signal();
} finally {
fullyUnlock();
}
}
/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
return drainTo(c, Integer.MAX_VALUE);
}
/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
if (c == null)
throw new NullPointerException();
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
boolean signalNotFull = false;
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
int n = Math.min(maxElements, count.get());
// count.get provides visibility to first n Nodes
Node<E> h = head;
int i = 0;
try {
while (i < n) {
Node<E> p = h.next;
c.add(p.item);
p.item = null;
h.next = h;
h = p;
++i;
}
return n;
} finally {
// Restore invariants even if c.add() threw
if (i > 0) {
// assert h.item == null;
head = h;
signalNotFull = (count.getAndAdd(-i) == capacity);
}
}
} finally {
takeLock.unlock();
if (signalNotFull)
signalNotFull();
}
}
/**
* Returns an iterator over the elements in this queue in proper sequence.
* The elements will be returned in order from first (head) to last (tail).
*
* <p>The returned iterator is
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*
* @return an iterator over the elements in this queue in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
/*
* Basic weakly-consistent iterator. At all times hold the next
* item to hand out so that if hasNext() reports true, we will
* still have it to return even if lost race with a take etc.
*/
private Node<E> current;
private Node<E> lastRet;
private E currentElement;
Itr() {
fullyLock();
try {
current = head.next;
if (current != null)
currentElement = current.item;
} finally {
fullyUnlock();
}
}
public boolean hasNext() {
return current != null;
}
/**
* Returns the next live successor of p, or null if no such.
*
* Unlike other traversal methods, iterators need to handle both:
* - dequeued nodes (p.next == p)
* - (possibly multiple) interior removed nodes (p.item == null)
*/
private Node<E> nextNode(Node<E> p) {
for (;;) {
Node<E> s = p.next;
if (s == p)
return head.next;
if (s == null || s.item != null)
return s;
p = s;
}
}
public E next() {
fullyLock();
try {
if (current == null)
throw new NoSuchElementException();
E x = currentElement;
lastRet = current;
current = nextNode(current);
currentElement = (current == null) ? null : current.item;
return x;
} finally {
fullyUnlock();
}
}
public void remove() {
if (lastRet == null)
throw new IllegalStateException();
fullyLock();
try {
Node<E> node = lastRet;
lastRet = null;
for (Node<E> trail = head, p = trail.next;
p != null;
trail = p, p = p.next) {
if (p == node) {
unlink(p, trail);
break;
}
}
} finally {
fullyUnlock();
}
}
}
/** A customized variant of Spliterators.IteratorSpliterator */
static final class LBQSpliterator<E> implements Spliterator<E> {
static final int MAX_BATCH = 1 << 25; // max batch array size;
final ResizableCapacityLinkedBlockIngQueue<E> queue;
Node<E> current; // current node; null until initialized
int batch; // batch size for splits
boolean exhausted; // true when no more nodes
long est; // size estimate
LBQSpliterator(ResizableCapacityLinkedBlockIngQueue<E> queue) {
this.queue = queue;
this.est = queue.size();
}
public long estimateSize() { return est; }
public Spliterator<E> trySplit() {
Node<E> h;
final ResizableCapacityLinkedBlockIngQueue<E> q = this.queue;
int b = batch;
int n = (b <= 0) ? 1 : (b >= MAX_BATCH) ? MAX_BATCH : b + 1;
if (!exhausted &&
((h = current) != null || (h = q.head.next) != null) &&
h.next != null) {
Object[] a = new Object[n];
int i = 0;
Node<E> p = current;
q.fullyLock();
try {
if (p != null || (p = q.head.next) != null) {
do {
if ((a[i] = p.item) != null)
++i;
} while ((p = p.next) != null && i < n);
}
} finally {
q.fullyUnlock();
}
if ((current = p) == null) {
est = 0L;
exhausted = true;
}
else if ((est -= i) < 0L)
est = 0L;
if (i > 0) {
batch = i;
return Spliterators.spliterator
(a, 0, i, Spliterator.ORDERED | Spliterator.NONNULL |
Spliterator.CONCURRENT);
}
}
return null;
}
public void forEachRemaining(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
final ResizableCapacityLinkedBlockIngQueue<E> q = this.queue;
if (!exhausted) {
exhausted = true;
Node<E> p = current;
do {
E e = null;
q.fullyLock();
try {
if (p == null)
p = q.head.next;
while (p != null) {
e = p.item;
p = p.next;
if (e != null)
break;
}
} finally {
q.fullyUnlock();
}
if (e != null)
action.accept(e);
} while (p != null);
}
}
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null) throw new NullPointerException();
final ResizableCapacityLinkedBlockIngQueue<E> q = this.queue;
if (!exhausted) {
E e = null;
q.fullyLock();
try {
if (current == null)
current = q.head.next;
while (current != null) {
e = current.item;
current = current.next;
if (e != null)
break;
}
} finally {
q.fullyUnlock();
}
if (current == null)
exhausted = true;
if (e != null) {
action.accept(e);
return true;
}
}
return false;
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.NONNULL |
Spliterator.CONCURRENT;
}
}
/**
* Returns a {@link Spliterator} over the elements in this queue.
*
* <p>The returned spliterator is
* <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
*
* <p>The {@code Spliterator} reports {@link Spliterator#CONCURRENT},
* {@link Spliterator#ORDERED}, and {@link Spliterator#NONNULL}.
*
* @implNote
* The {@code Spliterator} implements {@code trySplit} to permit limited
* parallelism.
*
* @return a {@code Spliterator} over the elements in this queue
* @since 1.8
*/
public Spliterator<E> spliterator() {
return new LBQSpliterator<E>(this);
}
/**
* Saves this queue to a stream (that is, serializes it).
*
* @param s the stream
* @throws java.io.IOException if an I/O error occurs
* @serialData The capacity is emitted (int), followed by all of
* its elements (each an {@code Object}) in the proper order,
* followed by a null
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
fullyLock();
try {
// Write out any hidden stuff, plus capacity
s.defaultWriteObject();
// Write out all elements in the proper order.
for (Node<E> p = head.next; p != null; p = p.next)
s.writeObject(p.item);
// Use trailing null as sentinel
s.writeObject(null);
} finally {
fullyUnlock();
}
}
/**
* Reconstitutes this queue from a stream (that is, deserializes it).
* @param s the stream
* @throws ClassNotFoundException if the class of a serialized object
* could not be found
* @throws java.io.IOException if an I/O error occurs
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in capacity, and any hidden stuff
s.defaultReadObject();
count.set(0);
last = head = new Node<E>(null);
// Read in all elements and place in queue
for (;;) {
@SuppressWarnings("unchecked")
E item = (E)s.readObject();
if (item == null)
break;
add(item);
}
}
}
\ No newline at end of file
package com.srthinker.statinfo.update;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.preference.PreferenceManager;
import androidx.annotation.StringRes;
import androidx.core.content.SharedPreferencesCompat;
import com.srthinker.generaltool.utils.JsonUtil;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* 本地存储的相关类
*
* @author liwanlian
* @date 2020/12/31 17:41
*/
public class SharedPreferencesUtil {
private static SharedPreferencesUtil sharedPreferencesUtil;
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
private static SharedPreferencesCompat.EditorCompat editorCompat = SharedPreferencesCompat.EditorCompat.getInstance();
private static final int DEFAULT_INT = 0;
private static final float DEFAULT_FLOAT = 0.0f;
private static final String DEFAULT_STRING = "";
private static final boolean DEFAULT_BOOLEAN = false;
private static final Set<String> DEFAULT_STRING_SET = new HashSet<>(0);
private static Context context;
private SharedPreferencesUtil(Context context) {
SharedPreferencesUtil.context = context.getApplicationContext();
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(SharedPreferencesUtil.context);
editor = sharedPreferences.edit();
}
public static SharedPreferencesUtil getInstance(Context context) {
if (sharedPreferencesUtil == null) {
sharedPreferencesUtil = new SharedPreferencesUtil(context);
}
return sharedPreferencesUtil;
}
public SharedPreferencesUtil put(@StringRes int key, Object value) {
return put(context.getString(key), value);
}
public SharedPreferencesUtil put(String key, Object value) {
if (value == null) {
return sharedPreferencesUtil;
}
if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
} else if (value instanceof Long) {
editor.putLong(key, (Long) value);
} else if (value instanceof Set) {
editor.putStringSet(key, (Set) value);
} else {
editor.putString(key, JsonUtil.getJsonString(value));
}
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public <T extends Object> T get(@StringRes int key, Class<T> clazz) {
String jsonString = (String) get(context.getString(key), "");
return JsonUtil.getObject(jsonString, clazz);
}
public <T extends Object> T get(String key, Class<T> clazz) {
String jsonString = (String) get(key, "");
return JsonUtil.getObject(jsonString, clazz);
}
public Object get(@StringRes int key, Object defaultObject) {
return get(context.getString(key), defaultObject);
}
public Object get(String key, Object defaultObject) {
if (defaultObject instanceof String) {
return sharedPreferences.getString(key, (String) defaultObject);
} else if (defaultObject instanceof Integer) {
return sharedPreferences.getInt(key, (int) defaultObject);
} else if (defaultObject instanceof Boolean) {
return sharedPreferences.getBoolean(key, (boolean) defaultObject);
} else if (defaultObject instanceof Float) {
return sharedPreferences.getFloat(key, (float) defaultObject);
} else if (defaultObject instanceof Long) {
return sharedPreferences.getLong(key, (long) defaultObject);
}
return null;
}
public SharedPreferencesUtil putInt(String key, int value) {
editor.putInt(key, value);
editorCompat.apply(editor);
return this;
}
public SharedPreferencesUtil putInt(@StringRes int key, int value) {
return putInt(context.getString(key), value);
}
public int getInt(@StringRes int key) {
return getInt(context.getString(key));
}
public int getInt(@StringRes int key, int defValue) {
return getInt(context.getString(key), defValue);
}
public int getInt(String key) {
return getInt(key, DEFAULT_INT);
}
public int getInt(String key, int defValue) {
return sharedPreferences.getInt(key, defValue);
}
public SharedPreferencesUtil putFloat(@StringRes int key, float value) {
return putFloat(context.getString(key), value);
}
public SharedPreferencesUtil putFloat(String key, float value) {
editor.putFloat(key, value);
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public float getFloat(String key) {
return getFloat(key, DEFAULT_FLOAT);
}
public float getFloat(String key, float defValue) {
return sharedPreferences.getFloat(key, defValue);
}
public float getFloat(@StringRes int key) {
return getFloat(context.getString(key));
}
public float getFloat(@StringRes int key, float defValue) {
return getFloat(context.getString(key), defValue);
}
public SharedPreferencesUtil putLong(@StringRes int key, long value) {
return putLong(context.getString(key), value);
}
public SharedPreferencesUtil putLong(String key, long value) {
editor.putLong(key, value);
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public long getLong(String key) {
return getLong(key, DEFAULT_INT);
}
public long getLong(String key, long defValue) {
return sharedPreferences.getLong(key, defValue);
}
public long getLong(@StringRes int key) {
return getLong(context.getString(key));
}
public long getLong(@StringRes int key, long defValue) {
return getLong(context.getString(key), defValue);
}
public SharedPreferencesUtil putString(@StringRes int key, String value) {
return putString(context.getString(key), value);
}
public SharedPreferencesUtil putString(String key, String value) {
editor.putString(key, value);
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public String getString(String key) {
return getString(key, DEFAULT_STRING);
}
public String getString(String key, String defValue) {
return sharedPreferences.getString(key, defValue);
}
public String getString(@StringRes int key) {
return getString(context.getString(key), DEFAULT_STRING);
}
public String getString(@StringRes int key, String defValue) {
return getString(context.getString(key), defValue);
}
public SharedPreferencesUtil putBoolean(@StringRes int key, boolean value) {
return putBoolean(context.getString(key), value);
}
public SharedPreferencesUtil putBoolean(String key, boolean value) {
editor.putBoolean(key, value);
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public boolean getBoolean(String key) {
return getBoolean(key, DEFAULT_BOOLEAN);
}
public boolean getBoolean(String key, boolean defValue) {
return sharedPreferences.getBoolean(key, defValue);
}
public boolean getBoolean(@StringRes int key) {
return getBoolean(context.getString(key));
}
public boolean getBoolean(@StringRes int key, boolean defValue) {
return getBoolean(context.getString(key), defValue);
}
public SharedPreferencesUtil putStringSet(@StringRes int key, Set<String> value) {
return putStringSet(context.getString(key), value);
}
public SharedPreferencesUtil putStringSet(String key, Set<String> value) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
editor.putStringSet(key, value);
editorCompat.apply(editor);
}
return sharedPreferencesUtil;
}
public Set<String> getStringSet(String key) {
return getStringSet(key, DEFAULT_STRING_SET);
}
public Set<String> getStringSet(String key, Set<String> defValue) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return sharedPreferences.getStringSet(key, defValue);
} else {
return DEFAULT_STRING_SET;
}
}
public Set<String> getStringSet(@StringRes int key) {
return getStringSet(context.getString(key));
}
public Set<String> getStringSet(@StringRes int key, Set<String> defValue) {
return getStringSet(context.getString(key), defValue);
}
public boolean contains(String key) {
return sharedPreferences.contains(key);
}
public boolean contains(@StringRes int key) {
return contains(context.getString(key));
}
public Map<String, ?> getAll() {
return sharedPreferences.getAll();
}
public SharedPreferencesUtil remove(@StringRes int key) {
return remove(context.getString(key));
}
public SharedPreferencesUtil remove(String key) {
editor.remove(key);
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public SharedPreferencesUtil clear() {
editor.clear();
editorCompat.apply(editor);
return sharedPreferencesUtil;
}
public SharedPreferences getSharedPreferences() {
return sharedPreferences;
}
}
package com.srthinker.statinfo.update;
/**
* @author liwanlian
* @date 2023/3/3 11:48
*/
public class UpdateInfo {
private String downloadUrl;
private String downloadVerify;
private String description;
private String name;
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDownloadVerify() {
return downloadVerify;
}
public void setDownloadVerify(String downloadVerify) {
this.downloadVerify = downloadVerify;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.srthinker.statinfo.update.request;
/**
* @author liwanlian
* @date 2023/2/1 15:54
*/
public class BaseReqBean {
private String devSn;
private String devModel;
private String curAppVersion;
public String getDevSn() {
return devSn;
}
public void setDevSn(String devSn) {
this.devSn = devSn;
}
public String getDevModel() {
return devModel;
}
public void setDevModel(String devModel) {
this.devModel = devModel;
}
public String getCurAppVersion() {
return curAppVersion;
}
public void setCurAppVersion(String curAppVersion) {
this.curAppVersion = curAppVersion;
}
}
package com.srthinker.statinfo.update.request;
/**
* @author liwanlian
* @date 2023/3/7 9:49
*/
public class BaseReqData<T> {
/**
* 是否需要回调到上层
*/
private boolean isNeedCallBack;
/**
* 请求的数据
*/
private T requestData;
public boolean isNeedCallBack() {
return isNeedCallBack;
}
public void setNeedCallBack(boolean needCallBack) {
isNeedCallBack = needCallBack;
}
public T getRequestData() {
return requestData;
}
public void setRequestData(T requestData) {
this.requestData = requestData;
}
}
package com.srthinker.statinfo.update.request;
import com.srthinker.statinfo.update.EquipmentInfo;
public class GetDeviceInfoBySnReq {
private String devSn;
private EquipmentInfo equipmentInfo;
public String getDevSn() {
return devSn;
}
public void setDevSn(String devSn) {
this.devSn = devSn;
}
public EquipmentInfo getEquipmentInfo() {
return equipmentInfo;
}
public void setEquipmentInfo(EquipmentInfo equipmentInfo) {
this.equipmentInfo = equipmentInfo;
}
}
package com.srthinker.statinfo.update.request;
import com.srthinker.statinfo.update.EquipmentInfo;
/**
* @Author : liwanlian
* @Time : On 2022/4/26 12:43
* @Description : GetPlatformTokenReq
*/
public class GetPlatformTokenReq {
private String clientId = null;
private String deviceName = null;
private String productKey = null;
private String signmethod = null;
private String version = null;
private String timestamp = null;
private String sign = null;
private String devSn;
private EquipmentInfo equipmentInfo;
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getProductKey() {
return productKey;
}
public void setProductKey(String productKey) {
this.productKey = productKey;
}
public String getSignmethod() {
return signmethod;
}
public void setSignmethod(String signmethod) {
this.signmethod = signmethod;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getDevSn() {
return devSn;
}
public void setDevSn(String devSn) {
this.devSn = devSn;
}
public EquipmentInfo getEquipmentInfo() {
return equipmentInfo;
}
public void setEquipmentInfo(EquipmentInfo equipmentInfo) {
this.equipmentInfo = equipmentInfo;
}
}
package com.srthinker.statinfo.update.request;
/**
* @Author : liwanlian
* @Time : On 2022/5/10 17:54
* @Description : GetLastestVersionReq
*/
public class GetVersionFromPlatformReq {
private String hardTypeName;
private String deviceSn;
public String getDeviceSn() {
return deviceSn;
}
public void setDeviceSn(String deviceSn) {
this.deviceSn = deviceSn;
}
public String getHardTypeName() {
return hardTypeName;
}
public void setHardTypeName(String hardTypeName) {
this.hardTypeName = hardTypeName;
}
}
package com.srthinker.statinfo.update.response;
/**
* @Author : liwanlian
* @Time : On 2022/4/26 14:35
* @Description : GetTokenResp
*/
public class GetPlatformTokenResp {
private Integer code;
private String msg;
private DataDTO data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public DataDTO getData() {
return data;
}
public void setData(DataDTO data) {
this.data = data;
}
public static class DataDTO {
private String responseMessageId;
private String responseTime;
private TokenDTO token;
public String getResponseMessageId() {
return responseMessageId;
}
public void setResponseMessageId(String responseMessageId) {
this.responseMessageId = responseMessageId;
}
public String getResponseTime() {
return responseTime;
}
public void setResponseTime(String responseTime) {
this.responseTime = responseTime;
}
public TokenDTO getToken() {
return token;
}
public void setToken(TokenDTO token) {
this.token = token;
}
public static class TokenDTO {
private String access_token;
private Integer accountLevel;
private Long expires_in;
private String token_type;
private String userId;
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public Integer getAccountLevel() {
return accountLevel;
}
public void setAccountLevel(Integer accountLevel) {
this.accountLevel = accountLevel;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
}
}
package com.srthinker.statinfo.update.response;
/**
* @Author : liwanlian
* @Time : On 2022/5/10 16:48
* @Description : UpdateNewInfo
*/
public class GetVersionFromPlatformResp {
private Integer id;
private String name;
private String hardTypeName;
private Object hardTypeId;
private String downloadUrl;
private String downloadVerify;
private Integer downloadSize;
private String createTime;
private Object updateTime;
private Integer deleted;
private String description;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHardTypeName() {
return hardTypeName;
}
public void setHardTypeName(String hardTypeName) {
this.hardTypeName = hardTypeName;
}
public Object getHardTypeId() {
return hardTypeId;
}
public void setHardTypeId(Object hardTypeId) {
this.hardTypeId = hardTypeId;
}
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public String getDownloadVerify() {
return downloadVerify;
}
public void setDownloadVerify(String downloadVerify) {
this.downloadVerify = downloadVerify;
}
public Integer getDownloadSize() {
return downloadSize;
}
public void setDownloadSize(Integer downloadSize) {
this.downloadSize = downloadSize;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public Object getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Object updateTime) {
this.updateTime = updateTime;
}
public Integer getDeleted() {
return deleted;
}
public void setDeleted(Integer deleted) {
this.deleted = deleted;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
package com.srthinker.statinfo.util.common;
import android.view.View;
import java.util.HashMap;
import java.util.Map;
public class ClickUtil {
private static final Map<Integer, Long> sLastClickTimes = new HashMap<>();
private static final long CLICK_INTERVAL = 800; // 限制点击间隔为 800 毫秒
private static long lastClickTime = 0;
public static boolean isFastClick(View view) {
long now = System.currentTimeMillis();
int viewId = view.getId();
if (sLastClickTimes.containsKey(viewId)) {
long lastClickTime = sLastClickTimes.get(viewId);
if (now - lastClickTime < CLICK_INTERVAL) {
return true;
}
}
sLastClickTimes.put(viewId, now);
return false;
}
/**
* 判断是否为快速点击
* @param interval:连续点击的间隔时间
* @return true: 是快速点击,false: 不是快速点击
*/
public static boolean isFastClick(int interval) {
long interval_time = interval;
if (interval==0){
interval_time = CLICK_INTERVAL;
}
long currentTime = System.currentTimeMillis();
if (currentTime - lastClickTime < interval_time) {
return true;
}
lastClickTime = currentTime;
return false;
}
// 禁止点击某个控件
public static void disableClick(View view) {
view.setEnabled(false);
}
// 可以点击某个控件
public static void enableClick(View view) {
view.setEnabled(true);
}
}
package com.srthinker.statinfo.util.common;
import android.text.TextUtils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
public class DateUtil {
private static final String TAG = "DateUtil";
public static String getNowDateTime(String formatStr) {
String format = formatStr;
if (TextUtils.isEmpty(format)) {
format = "yyyyMMddHHmmss";
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(new Date());
}
public static String getNextDay(String format) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 1);
Date nextDay = calendar.getTime();
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(nextDay);
}
public static Date getNextDate(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, 1);
Date nextDay = calendar.getTime();
return nextDay;
}
public static String getNowDateTimeFull() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
return sdf.format(new Date());
}
public static String getNowDateTimeFormat() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
}
public static String getNowTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date());
}
public static String getNowYearCN() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年");
return sdf.format(new Date());
}
public static int getNowYear() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.YEAR);
}
public static int getNowMonth() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.MONTH) + 1;
}
public static int getNowDay() {
Calendar calendar = Calendar.getInstance();
return calendar.get(Calendar.DAY_OF_MONTH);
}
public static int getNowWeek(){
Calendar cal = Calendar.getInstance();
int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (week_index == 0) {
week_index = 7;
}
return week_index;
}
//将时间转化为星期几
public static String getNowWeekString(){
int weekIndex = getNowWeek();
switch (weekIndex){
case 1:
return "星期一";
case 2:
return "星期二";
case 3:
return "星期三";
case 4:
return "星期四";
case 5:
return "星期五";
case 6:
return "星期六";
case 7:
return "星期日";
default:
return "未知";
}
}
//某天转化成String类型日期时间
public static String getStringTime(Date d_date,String format){
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(d_date);
}
public static String getAddDate(String str, long day_num) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date old_date;
try {
old_date = sdf.parse(str);
} catch (Exception e) {
e.printStackTrace();
return "";
}
long time = old_date.getTime();
long diff_time = day_num * 24 * 60 * 60 * 1000;
// LogUtil.debug(TAG, "day_num="+day_num+", diff_time="+diff_time);
time += diff_time;
Date new_date = new Date(time);
return sdf.format(new_date);
}
//转化成长整型
public static long getTime(String str) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = sdf.parse(str);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}
public static long getTime(String str,String formatStr){
SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
try {
Date date = sdf.parse(str);
return date.getTime();
} catch (ParseException e) {
e.printStackTrace();
return 0;
}
}
//计算某天是星期几
public static int getWeekIndex(String s_date) {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date d_date;
try {
d_date = format.parse(s_date);
} catch (Exception e) {
e.printStackTrace();
return 1;
}
Calendar cal = Calendar.getInstance();
cal.setTime(d_date);
int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (week_index == 0) {
week_index = 7;
}
return week_index;
}
//获取某天所在的月份
public static int getSelectedMonth(String s_date) {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date d_date;
try {
d_date = format.parse(s_date);
} catch (Exception e) {
e.printStackTrace();
return 1;
}
Calendar cal = Calendar.getInstance();
cal.setTime(d_date);
int month = cal.get(Calendar.MONTH) + 1;
return month;
}
//获取所在时间的周一的日期和周日的日期
public static String[] getMonAndSunDate(String s_date){
String[] getString = new String[2];
//先计算该时间是星期几
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date d_date;
try {
d_date = format.parse(s_date);
} catch (Exception e) {
e.printStackTrace();
return null;
}
Calendar cal = Calendar.getInstance();
cal.setTime(d_date);
int week_index = cal.get(Calendar.DAY_OF_WEEK) - 1;
if (week_index == 0) {
week_index = 7;
}
//获取所在周的周一日期
cal.add(Calendar.DAY_OF_MONTH,-week_index+1);
Date date1 = cal.getTime();
getString[0] = format.format(date1);
//Log.d(TAG, "getMondayDate: getString[0]="+getString[0]);
//获取所在周的周日日期
cal.add(Calendar.DAY_OF_MONTH,6);
Date date2 = cal.getTime();
//Log.d(TAG, "getMondayDate: getString[1]="+getString[1]);
getString[1] = format.format(date2);
return getString;
}
//判断某个日期是否是某一周的星期一到星期日
public static boolean isDateInWeek(String s_date,String s_date_target){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d_date;
Date d_date_target;
try {
d_date = format.parse(s_date);
d_date_target = format.parse(s_date_target);
} catch (Exception e) {
e.printStackTrace();
return false;
}
Calendar cal = Calendar.getInstance();
//西方周日为第一天,中国周一为第一天,需要设置星期一为第一天
cal.setFirstDayOfWeek(2);
cal.setTime(d_date_target);
int targetWeek = cal.get(Calendar.WEEK_OF_YEAR);
cal.setTime(d_date);
//获取待判断日期所在的周数。
int week = cal.get(Calendar.WEEK_OF_YEAR);
//判断待判断日期所在的周数是否等于目标周数,如果不等于则返回false。
if (week != targetWeek){
return false;
}else{
return true;
}
/*//判断待判断日期是否是星期一到星期日的其中一个,如果是则返回true,否则返回false。
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK)-1;
if (dayOfWeek == 0){
dayOfWeek = 7;
}
return dayOfWeek >= 1 && dayOfWeek <= 7;*/
}
//计算两个String类型之前的相差值是多少秒
public static long calculTimeDiffer(String formatStr,String time1,String time2){
long result = -1;
try {
SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
// 将字符串时间解析为Date对象
Date date1 = sdf.parse(time1);
Date date2 = sdf.parse(time2);
// 获取较大的时间
Date maxDate = date1.after(date2) ? date1 : date2;
Date minDate = date1.before(date2) ? date1 : date2;
// 计算时间差值(毫秒)
long diffInMillis = maxDate.getTime() - minDate.getTime();
// 将毫秒转换为秒
result = TimeUnit.MILLISECONDS.toSeconds(diffInMillis);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static final String DEFAULT_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
public static String getNowDateTime() {
return getFormattedDateTime(new Date(), DEFAULT_FORMAT);
}
public static String getFormattedDateTime(Date date, String format) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
formatter.setTimeZone(TimeZone.getDefault());
return formatter.format(date);
}
public static Date parseDateTime(String dateTimeString, String format){
SimpleDateFormat formatter = new SimpleDateFormat(format);
formatter.setTimeZone(TimeZone.getDefault());
try {
return formatter.parse(dateTimeString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
private static String toLocalZoneFormattedDateTime(Date date, String format) {
SimpleDateFormat formatter = new SimpleDateFormat(format);
formatter.setTimeZone(TimeZone.getDefault());
return formatter.format(date);
}
private static Date fromLocalZoneFormattedDateTime(String dateTimeString, String format){
SimpleDateFormat formatter = new SimpleDateFormat(format);
formatter.setTimeZone(TimeZone.getDefault());
try {
return formatter.parse(dateTimeString);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
public static String getDateFormattedZone(Date date,String format){
String formattedDateTime = DateUtil.getFormattedDateTime(date, format);
Date date1 = DateUtil.parseDateTime(formattedDateTime, format);
String localZoneFormattedDateTime = DateUtil.toLocalZoneFormattedDateTime(date1, DEFAULT_FORMAT);
return localZoneFormattedDateTime;
}
public static String zoneToDateString(String zoneString,String format){
Date date = fromLocalZoneFormattedDateTime(zoneString, DEFAULT_FORMAT);
return getFormattedDateTime(date, format);
}
//时间相差为多少s,先将字符串转化成date再比较
public static long getTimeDifference(String format,String time1, String time2) {
DateFormat dateFormat = new SimpleDateFormat(format);
try {
Date date1 = dateFormat.parse(time1);
Date date2 = dateFormat.parse(time2);
if (date1 != null && date2!=null) {
long diffInMillis = Math.abs(date1.getTime() - date2.getTime());
long diffInSeconds = diffInMillis / 1000;
return diffInSeconds;
}
return -1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
package com.srthinker.statinfo.util.common;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FileUtil {
private static final String TAG = "FileUtil";
// 判断文件是否已经存在的方法
public static boolean isFileExists(String filePath) {
File file = new File(filePath);
return file.exists();
}
//通过保存路径获取文件名
public static String getSaveName(String savePath){
if (TextUtils.isEmpty(savePath)){
return "";
}
int index = savePath.lastIndexOf("/");
if (index != -1 && index <savePath.length()-1){
return savePath.substring(index+1);
}else{
return "";
}
}
// 获取文件扩展名的方法
public static String getFileExtension(String fileName) {
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex != -1 && dotIndex < fileName.length() - 1) {
return fileName.substring(dotIndex);
} else {
return "";
}
}
// 在文件名和扩展名之间添加序号的方法(也有可能是没有拓展名的)
public static String addSerialNumber(String filePath, String fileName, int number) {
String extension = getFileExtension(fileName);
Log.i(TAG, "addSerialNumber: fileName="+fileName);
// 判断文件名是否已经包含序号
int index = fileName.lastIndexOf("(");
String newFileName = null;
if (index != -1) {
// 获取文件名中的序号
String numberStr = fileName.substring(index + 1, fileName.length() - 1);
try {
int existingNumber = Integer.parseInt(numberStr);
// 判断获取的序号是否大于等于给定的序号
if (existingNumber >= number) {
// 给定的序号加1
number = existingNumber + 1;
}
} catch (NumberFormatException e) {
// 序号解析失败,不进行任何操作
}
if (TextUtils.isEmpty(extension)){
newFileName = fileName.substring(0, fileName.lastIndexOf("(") + 1) + number + ")";
}else{
// 构建新的文件名
newFileName = fileName.substring(0, fileName.lastIndexOf("(") + 1) + number + ")" + extension;
}
}else{
if (TextUtils.isEmpty(extension)){
newFileName = fileName+"(1)";
}else{
//第一次重复
newFileName = fileName.substring(0, fileName.lastIndexOf("."))+"(1)"+extension;
}
}
// 根据新的文件名构建新的文件路径
String newFilePath = filePath.substring(0, filePath.lastIndexOf(File.separator) + 1) + newFileName;
// Log.i(TAG, "addSerialNumber: newFileName="+newFileName);
// 判断新的文件名是否已经存在
boolean isFileExists = isFileExists(newFilePath);
if (isFileExists) {
// 如果新的文件名已经存在,则递归调用addSerialNumber方法,将序号加1
newFilePath = addSerialNumber(newFilePath, newFileName, number + 1);
}
return newFilePath;
}
/**
* 从下载路径中获取文件名
* @param downloadUrl
* @return
*/
public static String getFileName(String downloadUrl){
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf('/') + 1);
if (fileName == null || "".equals(fileName.trim())){
for (int i = 0; ; i++) {
//初始化获取文件信息
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) new URL(downloadUrl).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK){
String mine = conn.getHeaderField(i); //从返回的流中获取特定索引的头字段的值
if (mine==null) break;
//获取content-disposition返回字段,里面可能包含文件名
if ("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){
Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
if (m.find()) return m.group(1);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
fileName = UUID.randomUUID()+".tmp"; //如果都没有找到,默认取一个文件名
//有网卡标识数字(每个网卡都有唯一的标识号)以及CPU时间的唯一数字生成的一个16字节的二进制作为文件名
}
return fileName;
}
//获取文件类型,主要文件类型有:text、image、audio、video、application
public static String getFileType(String filePath) {
if (TextUtils.isEmpty(filePath)){
return "";
}
String fileType = "";
String extension = MimeTypeMap.getFileExtensionFromUrl(filePath); // 获取文件扩展名
if (extension != null) {
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); // 根据扩展名获取文件类型
if (!TextUtils.isEmpty(mimeType)){
int index = mimeType.indexOf("/");
if (index != -1 && index<=mimeType.length()-1){
fileType = mimeType.substring(0,index);
}
}
}
return fileType;
}
/**
* 获取某路径中的文本内容
* @param filePath
* @return
*/
public static String readTextFromFile(String filePath) {
File file = new File(filePath);
StringBuilder text = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
boolean firstLine = true;
while ((line = br.readLine()) != null) {
if (firstLine){
firstLine = false;
}else{
text.append('\n');
}
text.append(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return text.toString();
}
public static boolean deleteFile(String filePath){
if (isFileExists(filePath)) {
return new File(filePath).delete();
}
return false;
};
/**
* 创建文件
*
* @param filePath 文件地址
* @param fileName 文件名
* @return
*/
public static boolean createFile(String filePath, String fileName) {
String strFilePath = filePath + fileName;
File file = new File(filePath);
if (!file.exists()) {
/** 注意这里是 mkdirs()方法 可以创建多个文件夹 */
file.mkdirs();
}
File subfile = new File(strFilePath);
if (!subfile.exists()) {
try {
boolean b = subfile.createNewFile();
return b;
} catch (IOException e) {
e.printStackTrace();
}
} else {
return true;
}
return false;
}
/**
* 遍历文件夹下的文件
*
* @param file 地址
*/
public static List<File> getFile(File file) {
List<File> list = new ArrayList<>();
File[] fileArray = file.listFiles();
if (fileArray == null) {
return null;
} else {
for (File f : fileArray) {
if (f.isFile()) {
list.add(0, f);
} else {
getFile(f);
}
}
}
return list;
}
/**
* 删除文件
*
* @param filePath 文件地址
* @return
*/
public static boolean deleteFiles(String filePath) {
List<File> files = getFile(new File(filePath));
if (files.size() != 0) {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
/** 如果是文件则删除 如果都删除可不必判断 */
/*if (file.isFile()) {
file.delete();
}*/
}
}
return true;
}
/**
* 向文件中添加内容
*
* @param strcontent 内容
* @param filePath 地址
* @param fileName 文件名
*/
public static void writeToFile(String strcontent, String filePath, String fileName) {
//生成文件夹之后,再生成文件,不然会出错
String strFilePath = filePath + fileName;
// 每次写入时,都换行写
File subfile = new File(strFilePath);
RandomAccessFile raf = null;
try {
/** 构造函数 第二个是读写方式 */
raf = new RandomAccessFile(subfile, "rw");
/** 将记录指针移动到该文件的最后 */
raf.seek(subfile.length());
/** 向文件末尾追加内容 */
raf.write(strcontent.getBytes());
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 修改文件内容(覆盖或者添加)
*
* @param path 文件地址
* @param content 覆盖内容
* @param append 指定了写入的方式,是覆盖写还是追加写(true=追加)(false=覆盖)
*/
public static void modifyFile(String path, String content, boolean append) {
try {
FileWriter fileWriter = new FileWriter(path, append);
BufferedWriter writer = new BufferedWriter(fileWriter);
writer.append(content);
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取文件内容
*
* @param filePath 地址
* @param filename 名称
* @return 返回内容
*/
public static String getString(String filePath, String filename) {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(new File(filePath + filename));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
InputStreamReader inputStreamReader = null;
try {
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
BufferedReader reader = new BufferedReader(inputStreamReader);
StringBuffer sb = new StringBuffer("");
String line;
try {
while ((line = reader.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* 重命名文件
*
* @param oldPath 原来的文件地址
* @param newPath 新的文件地址
*/
public static void renameFile(String oldPath, String newPath) {
File oleFile = new File(oldPath);
File newFile = new File(newPath);
//执行重命名
oleFile.renameTo(newFile);
}
/**
* 复制文件
*
* @param fromFile 要复制的文件目录
* @param toFile 要粘贴的文件目录
* @return 是否复制成功
*/
public static boolean copy(String fromFile, String toFile) {
//要复制的文件目录
File[] currentFiles;
File root = new File(fromFile);
//如同判断SD卡是否存在或者文件是否存在
//如果不存在则 return出去
if (!root.exists()) {
return false;
}
//如果存在则获取当前目录下的全部文件 填充数组
currentFiles = root.listFiles();
//目标目录
File targetDir = new File(toFile);
//创建目录
if (!targetDir.exists()) {
targetDir.mkdirs();
}
//遍历要复制该目录下的全部文件
for (int i = 0; i < currentFiles.length; i++) {
if (currentFiles[i].isDirectory())//如果当前项为子目录 进行递归
{
copy(currentFiles[i].getPath() + "/", toFile + currentFiles[i].getName() + "/");
} else//如果当前项为文件则进行文件拷贝
{
CopySdcardFile(currentFiles[i].getPath(), toFile + currentFiles[i].getName());
}
}
return true;
}
//文件拷贝
//要复制的目录下的所有非子目录(文件夹)文件拷贝
public static boolean CopySdcardFile(String fromFile, String toFile) {
try {
InputStream fosfrom = new FileInputStream(fromFile);
OutputStream fosto = new FileOutputStream(toFile);
byte bt[] = new byte[1024];
int c;
while ((c = fosfrom.read(bt)) > 0) {
fosto.write(bt, 0, c);
}
fosfrom.close();
fosto.close();
return true;
} catch (Exception ex) {
return false;
}
}
}
package com.srthinker.statinfo.util.common;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import java.util.ArrayList;
import java.util.List;
//需要添加依赖:implementation 'com.google.code.gson:gson:2.8.7'
public class GsonUtil {
/**
* 把json字符串转化为相对应的bean对象
* @param jsonString json字符串
* @param clazzBean 要封装成的目标对象
* @return 目标对象
*/
public static <T> T parserJsonToArrayBean(String jsonString,Class<T> clazzBean){
if(TextUtils.isEmpty(jsonString)){
throw new RuntimeException("json字符串为空");
}
JsonElement jsonElement = new JsonParser().parse(jsonString);
if(jsonElement.isJsonNull()){
throw new RuntimeException("json字符串为空");
}
if(!jsonElement.isJsonObject()){
throw new RuntimeException("json不是一个对象");
}
return new Gson().fromJson(jsonElement, clazzBean);
}
/**
* 把bean对象转化为json字符串
* @param obj bean对象
* @return 返回的是json字符串
*/
public static String toJsonString(Object obj){
if(obj!=null){
return new Gson().toJson(obj);
}else{
throw new RuntimeException("对象不能为空");
}
}
/**
*
* @param list 对象数组
* @return
*/
public static String ListToJson(List<?> list) {
if (list!=null){
Gson gson = new Gson();
return gson.toJson(list);
}else{
throw new RuntimeException("对象数组不能为空");
}
}
/**
* 将转化为一个对象数组
* @param jsonString json字符串
* @param beanClazz 集合里存入的数据对象
* @return 含有目标对象的集合
*/
public static <T> List<T> parserJsonToArrayBeans(String jsonString,Class<T> beanClazz){
if(TextUtils.isEmpty(jsonString)){
throw new RuntimeException("json字符串为空");
}
JsonElement jsonElement = new JsonParser().parse(jsonString);
if(jsonElement.isJsonNull()){
throw new RuntimeException("得到的jsonElement对象为空");
}
if(!jsonElement.isJsonArray()){
throw new RuntimeException("json字符不是一个数组对象集合");
}
JsonArray jsonArray = jsonElement.getAsJsonArray();
List<T> beans = new ArrayList<T>();
for (JsonElement jsonElement2: jsonArray) {
T bean = new Gson().fromJson(jsonElement2, beanClazz);
beans.add(bean);
}
return beans;
}
}
package com.srthinker.statinfo.util.common;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
public class HttpUtil {
// 将map型转为请求参数型
public static String urlencode(Map<String, String> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
* get方式的http请求
*
* @param httpUrl 请求地址
* @param paramStr 请求参数
* @return 返回结果
*/
public static String doGet(String httpUrl,String paramStr) {
HttpURLConnection connection = null;
InputStream inputStream = null;
BufferedReader bufferedReader = null;
String result = null;// 返回结果字符串
try {
httpUrl += "?"+paramStr;
// 创建远程url连接对象
URL url = new URL(httpUrl);
// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
connection = (HttpURLConnection) url.openConnection();
// 设置连接方式:get
connection.setRequestMethod("GET");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:60000毫秒
connection.setReadTimeout(60000);
// 设置请求头
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 发送请求
connection.connect();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
inputStream = connection.getInputStream();
// 封装输入流,并指定字符集
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
// 存放数据
StringBuilder sbf = new StringBuilder();
String temp;
while ((temp = bufferedReader.readLine()) != null) {
sbf.append(temp);
sbf.append(System.getProperty("line.separator"));
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != bufferedReader) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != inputStream) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (connection != null) {
connection.disconnect();// 关闭远程连接
}
}
return result;
}
/**
* post方式的http请求
*
* @param httpUrl 请求地址
* @param paramStr 请求参数
* @return 返回结果
*/
public static String doPost(String httpUrl, String paramStr) {
HttpURLConnection connection = null;
InputStream inputStream = null;
OutputStream outputStream = null;
BufferedReader bufferedReader = null;
String result = null;
try {
URL url = new URL(httpUrl);
// 通过远程url连接对象打开连接
connection = (HttpURLConnection) url.openConnection();
// 设置连接请求方式
connection.setRequestMethod("POST");
// 设置连接主机服务器超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取主机服务器返回数据超时时间:60000毫秒
connection.setReadTimeout(60000);
// 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
connection.setDoOutput(true);
// 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 通过连接对象获取一个输出流
outputStream = connection.getOutputStream();
// 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
outputStream.write(paramStr.getBytes());
// 通过连接对象获取一个输入流,向远程读取
if (connection.getResponseCode() == 200) {
inputStream = connection.getInputStream();
// 对输入流对象进行包装:charset根据工作项目组的要求来设置
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
StringBuilder sbf = new StringBuilder();
String temp;
// 循环遍历一行一行读取数据
while ((temp = bufferedReader.readLine()) != null) {
sbf.append(temp);
sbf.append(System.getProperty("line.separator"));
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != bufferedReader) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != outputStream) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != inputStream) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (connection != null) {
connection.disconnect();
}
}
return result;
}
}
package com.srthinker.statinfo.util.common;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
public class KeyBoardUtil {
public static void closeKeyboard(Activity Activity) {
InputMethodManager imm = (InputMethodManager) Activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(Activity.getWindow().getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
/**
* 软键盘监听器
*/
public static class SoftKeyBoardListener {
//activity的根视图
private View rootView;
//记录根视图的显示高度
int rootViewVisibleHeight;
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
public SoftKeyBoardListener(Activity activity) {
//获取activity的根视图
rootView = activity.getWindow().getDecorView();
//监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//获取当前根视图在屏幕上显示的大小
Rect r = new Rect();
//获取rootView在窗体的可视区域
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
if (rootViewVisibleHeight == visibleHeight) {
return;
}
//根视图显示高度变小超过200,可以看作软键盘显示了
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度变大超过200,可以看作软键盘隐藏了
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
/**
* 软键盘监听接口
*/
public interface OnSoftKeyBoardChangeListener {
// 键盘显示
void keyBoardShow(int height);
// 键盘隐藏
void keyBoardHide(int height);
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
}
}
package com.srthinker.statinfo.util.common;
import java.util.List;
public class MathUtil {
//想比较两个对象数组的内容是否相同,而不关心它们的顺序
public static <T> boolean areListsEqual(List<T> list1, List<T> list2) {
return list1.containsAll(list2) && list2.containsAll(list1);
}
}
package com.srthinker.statinfo.util.common;
/**
* @Description:
* @Author: gy
* @CreateDate: 2022/4/8 17:20
*/
public class Mutex {
private boolean syncLock;
public Mutex() {
// TODO Auto-generated constructor stub
syncLock=false;
}
/**
* @param timeout 等待锁的超时时间,单位:ms
* @return true 成功
* false 失败
**/
public synchronized boolean lock(int timeout){
if(syncLock==true){
try{
if(timeout==0){
wait();
}else{
wait(timeout);
if(syncLock==true){
return false;
}
}
}catch(Exception e){
e.printStackTrace();
return false;
}
}
syncLock=true;
return syncLock;
}
public synchronized boolean isLocked(){
return syncLock;
}
/**
* unlock
**/
public synchronized void unlock(){
syncLock=false;
notify();
}
}
package com.srthinker.statinfo.util.common;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
public class NetworkUtils {
public static String getIpAddress() {
String ipAddress = "";
try {
// 获取所有网络接口
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
// 过滤掉回环接口和未启用的接口
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
// 获取接口的所有IP地址
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
// 过滤掉IPv6地址和本地链路地址
if (inetAddress instanceof Inet6Address || inetAddress.isLinkLocalAddress()) {
continue;
}
// 获取IPv4地址
ipAddress = inetAddress.getHostAddress();
break;
}
// 如果找到了有效的IP地址,则跳出循环
if (!ipAddress.isEmpty()) {
break;
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return ipAddress;
}
public static String getIpAddress(Network network,Context context) {
String ipAddress = "";
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
LinkProperties linkProperties = connectivityManager.getLinkProperties(network);
for (LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
InetAddress inetAddress = linkAddress.getAddress();
String address = inetAddress.getHostAddress();
// 过滤掉IPv6地址和本地链路地址
if (inetAddress instanceof Inet6Address || inetAddress.isLinkLocalAddress()) {
continue;
}
// 添加IP地址到字符串列表
ipAddress += address + "\n";
}
} catch (Exception e) {
e.printStackTrace();
}
return ipAddress;
}
}
package com.srthinker.statinfo.util.common;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class PermissionUtil {
private final static String TAG = "PermissionUtil";
// 检查某个权限。返回true表示已启用该权限,返回false表示未启用该权限
public static boolean checkPermission(Activity act, String permission, int requestCode) {
Log.d(TAG, "checkPermission: "+permission);
boolean result = true;
// 只对Android6.0及以上系统进行校验
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 检查当前App是否开启了名称为permission的权限
int check = ContextCompat.checkSelfPermission(act, permission);
if (check != PackageManager.PERMISSION_GRANTED) {
// 未开启该权限,则请求系统弹窗,好让用户选择是否立即开启权限
ActivityCompat.requestPermissions(act, new String[]{permission}, requestCode);
result = false;
}
}
return result;
}
// 检查多个权限。返回true表示已完全启用权限,返回false表示未完全启用权限
public static boolean checkMultiPermission(Activity act, String[] permissions, int requestCode) {
boolean result = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int check = PackageManager.PERMISSION_GRANTED;
// 通过权限数组检查是否都开启了这些权限
for (String permission : permissions) {
check = ContextCompat.checkSelfPermission(act, permission);
if (check != PackageManager.PERMISSION_GRANTED) {
break;
}
}
if (check != PackageManager.PERMISSION_GRANTED) {
// 未开启该权限,则请求系统弹窗,好让用户选择是否立即开启权限
ActivityCompat.requestPermissions(act, permissions, requestCode);
result = false;
}
}
return result;
}
// 检查是否允许修改系统设置
public static boolean checkWriteSettings(Activity act, int requestCode) {
Log.d(TAG, "checkWriteSettings:");
boolean result = true;
// 只对Android6.0及Android7.0系统进行校验
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
// 检查当前App是否允许修改系统设置
if(!Settings.System.canWrite(act)){
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS,
Uri.parse("package:" + act.getPackageName()));
act.startActivityForResult(intent, requestCode);
Toast.makeText(act, "需要允许设置权限才能调节亮度噢", Toast.LENGTH_SHORT).show();
result = false;
}
}
return result;
}
public static void goActivity(Context ctx, Class<?> cls) {
Intent intent = new Intent(ctx, cls);
ctx.startActivity(intent);
}
}
package com.srthinker.statinfo.util.common;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
import java.util.List;
// 这是共享参数的工具类,统一对共享参数的读写操作
public class SharedUtil {
private static final String TAG = "SharedUtil";
private static SharedUtil mUtil; // 声明一个共享参数工具类的实例
private static SharedPreferences mShared; // 声明一个共享参数的实例
private static SharedPreferences.Editor mEditor;
private static Context ctx;
private SharedUtil(Context ctx){
SharedUtil.ctx = ctx.getApplicationContext();
// 从share.xml中获取共享参数对象
mShared = SharedUtil.ctx.getSharedPreferences("share", Context.MODE_PRIVATE);
mEditor = mShared.edit();
}
// 通过单例模式获取共享参数工具类的唯一实例
public static SharedUtil getInstance(Context ctx) {
if (mUtil == null) {
mUtil = new SharedUtil(ctx);
}
return mUtil;
}
// 把配对信息写入共享参数
public void writeShared(String key, String value) {
//SharedPreferences.Editor editor = mShared.edit(); // 获得编辑器的对象
mEditor.putString(key, value); // 添加一个指定键名的字符串参数
mEditor.commit(); // 提交编辑器中的修改
}
public void writeShared(String key,long value){
//SharedPreferences.Editor editor = mShared.edit(); // 获得编辑器的对象
mEditor.putLong(key, value); // 添加一个指定键名的字符串参数
mEditor.commit(); // 提交编辑器中的修改
}
public void writeShared(String key,int value){
//SharedPreferences.Editor editor = mShared.edit(); // 获得编辑器的对象
mEditor.putInt(key, value); // 添加一个指定键名的字符串参数
mEditor.commit(); // 提交编辑器中的修改
}
public void writeShared(int key, Object obj){
writeShared(String.valueOf(key),obj);
}
public void writeShared(int key,List<Object> objectList){
writeShared(String.valueOf(key),objectList);
}
//对象转化成String后保存
public void writeShared(String key,Object obj){
String value = null;
try {
value = GsonUtil.toJsonString(obj);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "readShared: e.message"+e.getMessage());
}
mEditor.putString(key, value); // 添加一个指定键名的字符串参数
mEditor.commit(); // 提交编辑器中的修改
}
//对象数组转化为String后保存
public void writeShared(String key, List<Object> objectList){
String value = null;
try {
value = GsonUtil.ListToJson(objectList);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "readShared: e.message"+e.getMessage());
}
mEditor.putString(key,value);
mEditor.commit();
}
// 根据键名到共享参数中查找对应的值对象
public String readShared(String key, String defaultValue) {
return mShared.getString(key, defaultValue);
}
public long readShared(String key, long defaultValue) {
return mShared.getLong(key, defaultValue);
}
public int readShared(String key,int defaultValue){
return mShared.getInt(key, defaultValue);
}
//将String转化回对象
public <T extends Object> T readSharedObject(String key,Class<T> clazz,String defaultValue){
String readString = readShared(key, defaultValue);
if (TextUtils.isEmpty(readString)){
return null;
}
try {
return GsonUtil.parserJsonToArrayBean(readString, clazz);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "readShared: e.message"+e.getMessage());
}
return null;
}
public <T extends Object> T readSharedObject(int key,Class<T> clazz,String defaultValue){
return readSharedObject(String.valueOf(key),clazz,defaultValue);
}
//将String转化为数组对象
public <T extends Object> List<T> readSharedList(String key,Class<T> clazz,String defaultValue){
String readString = readShared(key, defaultValue);
if (TextUtils.isEmpty(readString)){
return null;
}
try {
return GsonUtil.parserJsonToArrayBeans(readString, clazz);
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "readShared: e.message"+e.getMessage());
}
return null;
}
public <T extends Object> List<T> readSharedList(int key,Class<T> clazz,String defaultValue){
return readSharedList(String.valueOf(key),clazz,defaultValue);
}
}
package com.srthinker.statinfo.util.common;
import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
public class StatusBarUtil {
/**
* 根据传入的状态栏颜色自动设置字体颜色
* @param activity
* @param statusBarColor 比如:传入getResources().getColor(R.color.xxx)
*/
public static void setStatusBarColor(Activity activity, int statusBarColor) {
Window window = activity.getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(statusBarColor);
setStatusBarDarkMode(activity, isColorLight(statusBarColor));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
View statusBarView = createStatusBarView(activity, statusBarColor);
ViewGroup decorView = (ViewGroup) window.getDecorView();
decorView.addView(statusBarView);
setStatusBarDarkMode(activity, isColorLight(statusBarColor));
}
}
private static View createStatusBarView(Activity activity, int color) {
View statusBarView = new View(activity);
statusBarView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)));
statusBarView.setBackgroundColor(color);
return statusBarView;
}
private static int getStatusBarHeight(Activity activity) {
int statusBarHeight = 0;
int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
private static boolean isColorLight(int color) {
double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
return darkness < 0.5;
}
private static void setStatusBarDarkMode(Activity activity, boolean darkMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decorView = activity.getWindow().getDecorView();
int flags = decorView.getSystemUiVisibility();
if (darkMode) {
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decorView.setSystemUiVisibility(flags);
}
}
// 设置沉浸式状态栏,isLightStatusBar为true的话则状态栏字体颜色为黑色,反之白色
public static void setImmersiveStatusBar(Activity activity, boolean isLightStatusBar) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (isLightStatusBar) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
/**
* 隐藏导航栏和状态栏
*
* @param activity 当前活动
*/
public static void hideSystemUI(Activity activity) {
// 检查设备版本,只有在Android 4.0及以上版本才能隐藏导航栏和状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// 设置全屏标志
activity.getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE);
} else {
// 对于Android 4.0以下的设备,只隐藏标题栏
activity.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
}
/**
* 显示导航栏和状态栏
*
* @param activity 当前活动
*/
public static void showSystemUI(Activity activity) {
// 清除全屏标志
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
package com.srthinker.statinfo.util.common;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPool {
private static ThreadPool threadPool;
//可同时下载数
private int CORE_POOL_SIZE = 10;
//缓存队列的大小
private int MAX_POOL_SIZE = 20;
//超时时间(秒),如果超时则会被回收
private long KEEP_ALIVE = 10L;
public static ThreadPool getInstance(){
if (threadPool == null) {
synchronized (ThreadPool.class){
threadPool = new ThreadPool();
}
}
return threadPool;
}
private ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger();
@Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable,"download_thread--"+mCount.getAndIncrement());
}
};
private ThreadPoolExecutor threadPoolExecutor;
public void setCorePoolSize(int corePoolSize) {
if (corePoolSize == 0) {
return;
}
CORE_POOL_SIZE = corePoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
if (maxPoolSize == 0) {
return;
}
MAX_POOL_SIZE = maxPoolSize;
}
public int getCorePoolSize() {
return CORE_POOL_SIZE;
}
public int getMaxPoolSize() {
return MAX_POOL_SIZE;
}
public ThreadPoolExecutor getThreadPoolExecutor(){
if (threadPoolExecutor == null) {
threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(), sThreadFactory);
}
return threadPoolExecutor;
}
}
package com.srthinker.statinfo.util.common;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;
import androidx.core.content.FileProvider;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import me.jessyan.autosize.AutoSizeConfig;
import me.jessyan.autosize.onAdaptListener;
import me.jessyan.autosize.utils.ScreenUtils;
public class Utils {
private static final String TAG = "Utils";
// 根据手机的分辨率从 dp 的单位 转成为 px(像素)
public static int dip2px(Context context, float dpValue) {
// 获取当前手机的像素密度
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f); // 四舍五入取整
}
// 根据手机的分辨率从 px(像素) 的单位 转成为 dp
public static int px2dip(Context context, float pxValue) {
// 获取当前手机的像素密度
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f); // 四舍五入取整
}
// 获得屏幕的宽度
public static int getScreenWidth(Context ctx) {
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(dm);
return dm.widthPixels; // 返回屏幕的宽度数值
}
// 获得屏幕的高度
public static int getScreenHeight(Context ctx) {
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(dm);
return dm.heightPixels; // 返回屏幕的高度数值
}
// 获得屏幕的像素密度
public static float getScreenDensity(Context ctx) {
// 从系统服务中获取窗口管理器
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
// 从默认显示器中获取显示参数保存到dm对象中
wm.getDefaultDisplay().getMetrics(dm);
return dm.density; // 返回屏幕的像素密度数值
}
public static void installApp(Context pContext, File pFile){
if (null == pFile)
return;
if (!pFile.exists())
return;
Intent _Intent = new Intent();
_Intent.setAction(Intent.ACTION_VIEW);
Uri _uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
_Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
_Intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); //添加这一句表示对目标应用临时授权该Uri所代表的文件
_uri = FileProvider.getUriForFile(pContext, pContext.getPackageName() + ".fileProvider", pFile);
}else {
_uri = Uri.fromFile(pFile);
_Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
_Intent.setDataAndType(_uri, "application/vnd.android.package-archive");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
boolean hasInstallPermission = pContext.getPackageManager().canRequestPackageInstalls();
if (!hasInstallPermission) {
// 请求安装未知应用来源的权限
startInstallPermissionSettingActivity(pContext);
return;
}
}
pContext.startActivity(_Intent);
}
private static void startInstallPermissionSettingActivity(Context context) {
Uri packageUri = Uri.parse("package:" + context.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
//弹出toast
public static void showTips(Context context,String tips){
Activity activity = (Activity) context;
activity.runOnUiThread(()->{
Toast.makeText(context.getApplicationContext(), tips, Toast.LENGTH_SHORT).show();
});
}
//计算次数,有余数则加1
public static int mathCount(int number1,int number2){
if(number2==0 || number1==0){
return 0;
}
int count = number1 / number2;
if (number1%number2!=0){
count++;
}
return count;
}
public static Map<String, String> splitUrl(String url) {
Map<String, String> urlParts = new HashMap<>();
try {
URL parsedUrl = new URL(url);
String baseUrl = parsedUrl.getProtocol() + "://" + parsedUrl.getHost();
if (parsedUrl.getPort() != -1) {
baseUrl += ":" + parsedUrl.getPort();
}
String path = parsedUrl.getPath();
urlParts.put("baseUrl", baseUrl);
urlParts.put("path", path);
} catch (MalformedURLException e) {
e.printStackTrace();
}
return urlParts;
}
public static void autoSizeSwitch(Activity activity){
//屏幕适配监听器
AutoSizeConfig.getInstance().setOnAdaptListener(new onAdaptListener() {
@Override
public void onAdaptBefore(Object target, Activity activity) {
//使用以下代码, 可以解决横竖屏切换时的屏幕适配问题
//首先设置最新的屏幕尺寸,ScreenUtils.getScreenSize(activity) 的参数一定要不要传 Application !!!
AutoSizeConfig.getInstance().setScreenWidth(ScreenUtils.getScreenSize(activity)[0]);
AutoSizeConfig.getInstance().setScreenHeight(ScreenUtils.getScreenSize(activity)[1]);
//根据屏幕方向,设置设计尺寸
if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
//设置横屏设计尺寸
AutoSizeConfig.getInstance()
.setDesignWidthInDp(960)
.setDesignHeightInDp(540);
} else {
//设置竖屏设计尺寸
AutoSizeConfig.getInstance()
.setDesignWidthInDp(540)
.setDesignHeightInDp(960);
}
}
@Override
public void onAdaptAfter(Object target, Activity activity) {
}
});
}
//获取自己应用内部的版本号
public static int getVersionCode(Context context) {
PackageManager manager = context.getPackageManager();
int code = 0;
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
code = info.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return code;
}
//获取自己应用内部的版本名
public static String getVersionName(Context context) {
PackageManager manager = context.getPackageManager();
String name = null;
try {
PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
name = info.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return name;
}
public static Integer version2Int(String version){
String replace = version.replace(".", "");
return Integer.parseInt(replace);
}
/*控制输入内容的可见*/
public static void setEditTextVisible(EditText editText) {
editText.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}
/*控制输入内容的不可见*/
public static void setEditTextInvisible(EditText editText) {
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
/** 判断字符串中是否包含数字 **/
public static boolean isContainsNum(String input) {
int len = input.length();
for (int i = 0; i < len; i++) {
if (Character.isDigit(input.charAt(i))) {
return true;
}
}
return false;
}
/**
* 通过对象的某个字段判断,如果有item的该字段重复则去重
* @param originalList 对象的列表
* @param fieldName 对象的某个字段
* @param <T> 某对象
* @return
*/
public static <T> List<T> removeDuplicates(List<T> originalList, String fieldName) {
Set<Object> set = new LinkedHashSet<>();
List<T> distinctList = new ArrayList<>();
for (T item : originalList) {
Object fieldValue = getFieldValue(item, fieldName);
if (!set.contains(fieldValue)) {
set.add(fieldValue);
distinctList.add(item);
}
}
return distinctList;
}
private static Object getFieldValue(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
//允许访问私有字段
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
* 将某个List列表倒序排序
* @param originalList
* @param <T>
* @return
*/
public static <T> List<T> reverseList(List<T> originalList) {
List<T> reversedList = new ArrayList<>(originalList);
Collections.reverse(reversedList);
return reversedList;
}
//返回true表示用限制使用
public static boolean isRootPermissionRestricted() {
boolean isRestricted = false;
Process process = null;
DataOutputStream os = null;
BufferedReader reader = null;
BufferedReader reader1 = null;
try {
//process = Runtime.getRuntime().exec("su");
process = Runtime.getRuntime().exec("srt");
os = new DataOutputStream(process.getOutputStream());
reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// 执行一个需要root权限的命令
os.writeBytes("ls /data\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line);
output.append("\n");
}
Log.i(TAG, "isRootPermissionRestricted: output="+output.toString());
// 检查返回结果是否包含权限被拒绝的提示
if (output.toString().contains("not allowed")) {
isRestricted = true;
}
reader1 = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder output1 = new StringBuilder();
String line1;
while ((line1 = reader1.readLine()) != null) {
output1.append(line1);
output1.append("\n");
}
// 检查返回结果是否包含权限被拒绝的提示
if (output1.toString().contains("Permission denied")) {
isRestricted = true;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.close();
}
if (reader != null) {
reader.close();
}
if (process != null) {
process.destroy();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isRestricted;
}
//需要传下载后的apk的绝对路径和当前上下文,这个方法的返回值表示为:安装成功是true,安装失败是false
//apkPath:apk文件的绝对路径
public static boolean clientInstall(String apkPath,Context context,String mainActivityPath) {
boolean result = false;
DataOutputStream dataOutputStream = null;
BufferedReader errorStream = null;
BufferedReader successStream = null;
Process process = null;
try {
// 申请 su 权限
//process = Runtime.getRuntime().exec("su");
//申请srt权限
process = Runtime.getRuntime().exec("srt");
dataOutputStream = new DataOutputStream(process.getOutputStream());
// 执行 pm install 命令 (这是apk安装命令)
String command = "pm install -r " + apkPath + "\n";
//执行 am start -n 命令 (这是apk重启命令) -----.MainActivity是默认重启app后要打开哪个界面
String runApp = "am start -n "+context.getPackageName()+"/"+context.getPackageName()+mainActivityPath+" >>/dev/null 2>&1;";
//这样子写也是可以的,用\n结尾也可以
// String runApp = "am start -n "+context.getPackageName()+"/"+context.getPackageName()+".MainActivity"+ "\n";
command=command+runApp;
Log.d("111333","走到这里,---------------打印静默安装命令="+command);
dataOutputStream.write(command.getBytes(Charset.forName("UTF-8")));
dataOutputStream.writeBytes("exit\n");
Log.d("111333","走到这里,---------------打印静默安装完成");
dataOutputStream.flush();
process.waitFor();
errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
StringBuilder errorMsg = new StringBuilder();
String line;
while ((line = errorStream.readLine()) != null) {
errorMsg.append(line);
}
Log.d("111333","走到这里,---------------silent install error message:{}="+errorMsg);
StringBuilder successMsg = new StringBuilder();
successStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
// 读取命令执行结果
while ((line = successStream.readLine()) != null) {
successMsg.append(line);
}
Log.d("111333","走到这里,---------------silent install success message:{}="+successMsg);
// 如果执行结果中包含 Failure 字样就认为是操作失败,否则就认为安装成功
if (!(errorMsg.toString().contains("Failure") || successMsg.toString().contains("Failure"))) {
result = true;
}
} catch (Exception e) {
Log.d("111333","走到这里,---------------e="+e);
} finally {
try {
if (process != null) {
process.destroy();
}
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (errorStream != null) {
errorStream.close();
}
if (successStream != null) {
successStream.close();
}
} catch (Exception e) {
// ignored
}
}
return result;
}
/**
* Silent install
*
* @param path Package
* @return true: success false: failed
*/
public static boolean installSilent(String path) {
boolean result = false;
BufferedReader es = null;
DataOutputStream os = null;
try {
Process process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
String command = "pm install -r " + path + "\n";
Log.i(TAG, "installSilent: command="+command);
os.write(command.getBytes(Charset.forName("utf-8")));
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
es = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line;
StringBuilder builder = new StringBuilder();
while ((line = es.readLine()) != null) {
builder.append(line);
}
Log.d(TAG, "install msg is " + builder.toString());
/* Installation is considered a Failure if the result contains
the Failure character, or a success if it is not.
*/
if (!builder.toString().contains("Failure")) {
result = true;
}
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
} finally {
try {
if (os != null) {
os.close();
}
if (es != null) {
es.close();
}
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
}
}
return result;
}
}
package com.srthinker.statinfo.util.other;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import android.util.Log;
import com.srthinker.statinfo.util.common.NetworkUtils;
public class NetworkIPMonitor {
private static final String TAG = "NetworkIPMonitor";
private Context mContext;
private ConnectivityManager mConnectivityManager;
private NetworkCallback mNetworkCallback;
private OnIPChangeCallback onIPChangeCallback;
public NetworkIPMonitor(Context context) {
mContext = context;
mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mNetworkCallback = new NetworkCallback();
}
// 开始监测网络IP地址
public void startMonitoring() {
/*NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
String ipAddress = NetworkUtils.getIpAddress();
int type = networkInfo.getType();
String networkType = getNetworkType(type);
Log.i(TAG, "startMonitoring: IP地址="+ipAddress);
Log.i(TAG, "startMonitoring: 网络类型="+networkType);
if (onIPChangeCallback!=null){
onIPChangeCallback.OnIPChange(ipAddress,networkType);
}
}*/
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
mConnectivityManager.registerNetworkCallback(request, mNetworkCallback);
}
// 停止监测网络IP地址
public void stopMonitoring() {
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
// 自定义网络回调
private class NetworkCallback extends ConnectivityManager.NetworkCallback {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
Log.i(TAG, "onAvailable: ");
// 获取IP地址
String ipAddress = getIPAddress(network);
String networkType = getNetworkType(network);
if (ipAddress != null && networkType != null) {
Log.d(TAG, "IP地址: " + ipAddress);
Log.d(TAG, "网络类型: " + networkType);
// 在这里处理IP地址和网络类型的变化
if (onIPChangeCallback!=null){
onIPChangeCallback.OnIPChange(ipAddress,networkType);
}
}
}
@Override
public void onLost(Network network) {
super.onLost(network);
// 在这里处理网络断开的情况
Log.d(TAG, "onLost: 无网络连接");
if (onIPChangeCallback != null) {
onIPChangeCallback.OnIPLost("无网络连接");
}
}
}
// 获取IP地址
private String getIPAddress(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//return mConnectivityManager.getLinkProperties(network).getLinkAddresses().toString();
String ipAddress = NetworkUtils.getIpAddress(network, mContext);
return ipAddress;
} else {
// 在Android M以下的版本中,可以通过其他方式获取IP地址
return null;
}
}
// 获取网络类型
private String getNetworkType(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NetworkCapabilities networkCapabilities = mConnectivityManager.getNetworkCapabilities(network);
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return "WiFi";
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return "4G";
} else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
return "以太网";
}
}
} else {
// 在Android M以下的版本中,可以通过其他方式获取网络类型
return null;
}
return null;
}
private String getNetworkType(int networkType) {
switch (networkType) {
case ConnectivityManager.TYPE_WIFI:
return "Wi-Fi";
case ConnectivityManager.TYPE_MOBILE:
return "移动网络";
case ConnectivityManager.TYPE_ETHERNET:
return "以太网";
default:
return "其他网络";
}
}
public interface OnIPChangeCallback{
void OnIPChange(String ipAddress,String networkType);
void OnIPLost(String error);
}
public void setOnIPChangeCallback(OnIPChangeCallback onIPChangeCallback){
this.onIPChangeCallback = onIPChangeCallback;
}
}
\ No newline at end of file
package com.srthinker.statinfo.wedget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import com.srthinker.statinfo.databinding.CustomEditBinding;
public class EditView extends LinearLayout {
private Context context;
private com.srthinker.statinfo.databinding.CustomEditBinding mBinding;
public EditView(Context context) {
super(context,null);
this.context = context;
initView(context);
}
public EditView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView(context);
}
private void initView(Context context) {
mBinding = CustomEditBinding.inflate(LayoutInflater.from(context), this, true);
}
public void initItem(String title,String hint){
mBinding.tvTitle.setText(title);
mBinding.etContent.setHint(hint);
}
public void setContent(String content){
mBinding.etContent.setText(content);
}
public void setContentIsFocus(boolean isFocus){
if (isFocus){
mBinding.etContent.setFocusableInTouchMode(true);
mBinding.etContent.setFocusable(true);
mBinding.etContent.requestFocus();
}else{
mBinding.etContent.setFocusable(false);
mBinding.etContent.setFocusableInTouchMode(false);
}
}
public String getContent(){
return mBinding.etContent.getText().toString();
}
public void setInputType(int type){
mBinding.etContent.setInputType(type);
}
public void setStatus(boolean status){
if (status){
mBinding.tvStatus.setVisibility(INVISIBLE);
}else{
mBinding.tvStatus.setVisibility(VISIBLE);
}
}
}
package com.srthinker.statinfo.wedget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import com.srthinker.statinfo.databinding.ViewGroupBinding;
public class GroupView extends LinearLayout {
private com.srthinker.statinfo.databinding.ViewGroupBinding mBinding;
private Context context;
public GroupView(Context context) {
super(context,null);
}
public GroupView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView(context);
}
private void initView(Context context) {
mBinding = ViewGroupBinding.inflate(LayoutInflater.from(context), this, true);
}
public void initItem(String desc,int number,int colorId){
mBinding.llItem.setBackgroundColor(context.getResources().getColor(colorId));
mBinding.tvDesc.setText(desc);
mBinding.etNumber.setText(number+"");
}
/*public HashMap<String,Integer> getItem(){
HashMap<String, Integer> resultMap = null;
String desc = mBinding.tvDesc.getText().toString();
int number = Integer.parseInt(mBinding.etNumber.getText().toString());
resultMap.put(desc,number);
return resultMap;
}*/
public int getNumber(){
int number = Integer.parseInt(mBinding.etNumber.getText().toString());
return number;
}
public void setNumber(int number){
mBinding.etNumber.setText(number+"");
}
}
package com.srthinker.statinfo.wedget;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import com.srthinker.statinfo.databinding.DialogLoadBinding;
public class LoadDialog extends Dialog {
private static LoadDialog loadDialog;
private final Context context;
private final com.srthinker.statinfo.databinding.DialogLoadBinding binding;
public LoadDialog(@NonNull Context context) {
super(context);
this.context = context;
binding = DialogLoadBinding.inflate(LayoutInflater.from(context));
setContentView(binding.getRoot());
initWindow();
}
/*public static LoadDialog getInstance(Context context){
if (loadDialog == null) {
synchronized (LoadDialog.class){
loadDialog = new LoadDialog(context);
}
}
return loadDialog;
}*/
private void initWindow() {
Window window = getWindow();
if (window != null) {
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.gravity = Gravity.CENTER;
window.setAttributes(layoutParams);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
setCanceledOnTouchOutside(false);
}
public void setContent(String content){
binding.tvLoadInfo.setText(content);
}
public void showDialog() {
if (!isShowing()) {
show();
}
}
public void dismissDialog() {
if (isShowing()) {
dismiss();
}
}
}
package com.srthinker.statinfo.wedget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.Nullable;
import com.srthinker.statinfo.databinding.ViewNumberBinding;
public class NumberView extends LinearLayout {
private Context context;
private com.srthinker.statinfo.databinding.ViewNumberBinding mBinding;
private TextView tvNumber;
private TextView tvDesc;
private RelativeLayout rl_item;
public NumberView(Context context) {
super(context,null);
}
public NumberView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.context = context;
initView();
}
private void initView() {
mBinding = ViewNumberBinding.inflate(LayoutInflater.from(context),this,true);
/*LayoutInflater.from(context).inflate(R.layout.view_number, this);
tvNumber = findViewById(R.id.tv_number);
tvDesc = findViewById(R.id.tv_desc);
rl_item = findViewById(R.id.rl_item);*/
}
public void initItem(int number,String desc,int drawId){
mBinding.tvNumber.setText(number+"");
mBinding.tvDesc.setText(desc);
mBinding.rlItem.setBackgroundResource(drawId);
/*tvNumber.setText(number+"");
tvDesc.setText(desc);
rl_item.setBackgroundResource(drawId);*/
}
public void setNumber(int number){
mBinding.tvNumber.setText(number+"");
}
public int getNumber(){
return Integer.parseInt(mBinding.tvNumber.getText().toString());
}
}
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@color/color_0287F9"/>
<item android:color="@color/white"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@color/color_0287F9"/>
<item android:color="@color/white"/>
</selector>
\ No newline at end of file
<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>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="1dp" android:color="@color/color_038BFF"/>
<solid android:color="@color/bg_060A38"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"/>
<stroke android:color="@color/color_2D52E3" android:width="1dp"/>
<corners android:radius="5dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_2D52E3"/>
<corners android:radius="5dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@mipmap/selected"/>
<item android:drawable="@mipmap/unselect"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line">
<!-- 显示虚线,破折线的宽度为dashWith,空隙的宽度为dashGap, darkgray -->
<stroke android:width="1dp" android:color="@color/color_0090FF"
android:dashWidth="1dp" android:dashGap="1dp" />
<size android:height="1dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"/>
<corners android:radius="20dp"/>
</shape>
\ No newline at end of file
<?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>
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<shape android:shape="rectangle">
<size android:width="40dp" android:height="3dp"/>
<solid android:color="@color/color_0287F9"/>
<corners android:radius="5dp"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<size android:width="40dp" android:height="3dp"/>
<solid android:color="@color/transparent"/>
<corners android:radius="5dp"/>
</shape>
</item>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/selected_10"/>
<item android:drawable="@drawable/unselect_10"/>
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:width="10dp" android:height="10dp">
<bitmap android:src="@mipmap/selected"/>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/grey"/>
<corners android:radius="20dp"/>
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:height="10dp" android:width="10dp">
<bitmap android:src="@mipmap/unselect"/>
</item>
</layer-list>
\ No newline at end of file
<?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"
android:id="@+id/baseContentView"
tools:context=".uis.BaseActivity">
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@color/bg_070A2E"
android:gravity="center"
tools:context=".uis.FlashActivity">
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textSize="@dimen/text_25"
android:textColor="@color/white"
android:textStyle="bold"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:background="@color/bg_070A2E"
android:orientation="vertical"
tools:context=".uis.GroupActivity">
<include layout="@layout/layout_top"/>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fcv_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:background="@color/bg_070A2E"
tools:context=".uis.MainActivity">
<RelativeLayout
android:layout_width="939.59dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/banner_top"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:text="@string/top_time"
android:textColor="@color/color_BDE4FF"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:gravity="center|left"
android:layout_alignParentRight="true"
android:layout_marginRight="96dp"
android:layout_marginTop="4dp"
android:textSize="@dimen/time_size"/>
<Button
android:id="@+id/btn_group_detail"
android:layout_width="60dp"
android:layout_height="22dp"
android:background="@color/color_2D52E3"
android:layout_alignParentRight="true"
android:layout_marginRight="8dp"
android:layout_marginTop="34dp"
android:gravity="center"
android:text="人员详情"
android:textColor="@color/white"
android:textSize="@dimen/text_10"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="9dp"
android:layout_marginLeft="18dp"
android:layout_marginRight="15dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="653dp"
android:layout_height="215dp"
android:background="@drawable/bg_shape"
android:padding="15dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="@string/text_01"
android:textSize="@dimen/text_10"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/line_bottom"
android:layout_marginTop="5dp"/>
<!-- <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginLeft="10dp"
android:orientation="horizontal">
<com.srthinker.statinfo.wedget.GroupView
android:id="@+id/gv_waterproof"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.srthinker.statinfo.wedget.GroupView
android:id="@+id/gv_outrigger"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.srthinker.statinfo.wedget.GroupView
android:id="@+id/gv_build"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.srthinker.statinfo.wedget.GroupView
android:id="@+id/gv_supervisor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>-->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginLeft="10dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="653dp"
android:layout_height="215dp"
android:layout_marginTop="15.5dp"
android:background="@drawable/bg_shape"
android:padding="15dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="@string/text_02"
android:textSize="@dimen/text_10"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/line_bottom"
android:layout_marginTop="5dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="29.5dp"
android:layout_marginLeft="100dp">
<com.srthinker.statinfo.wedget.NumberView
android:id="@+id/nv_enter"
android:layout_width="101.45dp"
android:layout_height="101.45dp"
android:layout_marginRight="74dp"/>
<com.srthinker.statinfo.wedget.NumberView
android:id="@+id/nv_leave"
android:layout_width="101.45dp"
android:layout_height="101.45dp"
android:layout_marginRight="74dp"/>
<com.srthinker.statinfo.wedget.NumberView
android:id="@+id/nv_present"
android:layout_width="101.45dp"
android:layout_height="101.45dp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="255.5dp"
android:layout_height="445.5dp"
android:background="@drawable/bg_shape"
android:layout_marginLeft="15dp"
android:padding="15dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:text="@string/text_03"
android:textSize="@dimen/text_10"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/line_bottom"
android:layout_marginTop="5dp"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="17dp">
<TextView
android:id="@+id/tv_enter_text"
android:layout_width="44dp"
android:layout_height="20dp"
android:gravity="center"
android:text="进"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:background="@color/color_00A89C"
android:layout_alignParentLeft="true"/>
<TextView
android:id="@+id/tv_enter_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="!"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:layout_toRightOf="@+id/tv_enter_text"
android:layout_alignBottom="@+id/tv_enter_text"
android:visibility="visible"
android:layout_marginLeft="5dp"/>
<TextView
android:id="@+id/tv_leave_text"
android:layout_width="44dp"
android:layout_height="20dp"
android:gravity="center"
android:text="出"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:background="@color/color_2D52E3"
android:layout_alignParentRight="true"/>
<TextView
android:id="@+id/tv_leave_error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="!"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:layout_toLeftOf="@+id/tv_leave_text"
android:layout_alignBottom="@+id/tv_leave_text"
android:visibility="visible"
android:layout_marginRight="5dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@+id/tv_enter_text"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_enter_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_leave_list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_device_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center"
android:textColor="@color/white"
android:textSize="@dimen/text_10"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="30dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:gravity="center"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:textColor="@color/black"
android:textSize="@dimen/text_12_5"
android:layout_gravity="center_vertical"
android:text=""
android:gravity="center|left"/>
<EditText
android:id="@+id/et_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="5"
android:textColor="@color/black"
android:textSize="@dimen/text_12_5"
android:layout_gravity="center_vertical"
android:gravity="center|right"
android:text=""
android:singleLine="true"
android:background="@null"
android:outlineProvider="none"/>
<TextView
android:id="@+id/tv_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/color_0287F9"
android:text="!"
android:paddingLeft="5dp"
android:visibility="invisible"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:focusableInTouchMode="true"
android:focusable="true"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="42dp"
android:background="@color/color_2D52E3">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center|left"
android:text=""
android:textColor="@color/white"
android:textSize="@dimen/text_13"
android:layout_centerVertical="true"
android:paddingLeft="15dp"/>
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_close"
android:layout_alignParentRight="true"
android:padding="15dp"
android:layout_centerVertical="true"/>
</RelativeLayout>
<TextView
android:id="@+id/tv_add_new_ip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_11"
android:text="+添加设备IP"
android:textColor="@color/color_2D52E3"
android:layout_gravity="right|center"
android:layout_marginRight="15dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:fillViewport="true">
<LinearLayout
android:id="@+id/ll_ips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.srthinker.statinfo.wedget.EditView
android:id="@+id/ev_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.srthinker.statinfo.wedget.EditView
android:id="@+id/ev_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<com.srthinker.statinfo.wedget.EditView
android:id="@+id/ev_serverip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
android:layout_width="84dp"
android:layout_height="32dp"
android:background="@drawable/button_bg_cancel"
android:text="取消"
android:textColor="@color/color_2D52E3"
android:textSize="@dimen/text_12_5"/>
<Button
android:id="@+id/btn_confirm"
android:layout_width="84dp"
android:layout_height="32dp"
android:background="@drawable/button_bg_confirm"
android:text="确定"
android:layout_marginLeft="30dp"
android:textColor="@color/white"
android:textSize="@dimen/text_12_5"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/dialog_rounded"
android:padding="20dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_load_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_25"
android:textColor="@color/black"
android:gravity="center"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="42dp"
android:layout_marginBottom="32dp"
android:background="@color/color_2D52E3">
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center|left"
android:text="人员分组"
android:textColor="@color/white"
android:textSize="@dimen/text_13"
android:layout_centerVertical="true"
android:paddingLeft="20dp"/>
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_close"
android:layout_alignParentRight="true"
android:padding="15dp"
android:layout_centerVertical="true"/>
</RelativeLayout>
<RadioGroup
android:id="@+id/rg_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rb_select_one"
style="@style/select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_one"/>
<RadioButton
android:id="@+id/rb_select_two"
style="@style/select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_two"/>
<RadioButton
android:id="@+id/rb_select_three"
style="@style/select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_three"/>
<RadioButton
android:id="@+id/rb_select_four"
style="@style/select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/select_four"/>
</RadioGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="36dp"
android:layout_marginBottom="32dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cancel"
android:layout_width="84dp"
android:layout_height="32dp"
android:background="@drawable/button_bg_cancel"
android:text="取消"
android:textColor="@color/color_2D52E3"
android:textSize="@dimen/text_12_5"/>
<Button
android:id="@+id/btn_confirm"
android:layout_width="84dp"
android:layout_height="32dp"
android:background="@drawable/button_bg_confirm"
android:text="确定"
android:layout_marginLeft="30dp"
android:textColor="@color/white"
android:textSize="@dimen/text_12_5"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg_070A2E"
android:paddingLeft="18dp"
android:paddingRight="18dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_back"
android:layout_centerVertical="true"/>
<TextView
android:id="@+id/tv_tab_no"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="未分组人员"
android:textSize="@dimen/text_11"
android:textColor="@color/text_select"
android:layout_toRightOf="@+id/iv_back"
android:layout_marginLeft="17dp"
android:drawablePadding="5.5dp"
android:drawableBottom="@drawable/indicator"
android:layout_marginTop="4dp"/>
<TextView
android:id="@+id/tv_tab_yes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已分组人员"
android:textSize="@dimen/text_11"
android:textColor="@color/text_select"
android:layout_toRightOf="@+id/iv_back"
android:layout_marginLeft="102dp"
android:drawablePadding="5.5dp"
android:drawableBottom="@drawable/indicator"
android:layout_marginTop="4dp"/>
<Button
android:id="@+id/btn_grouping"
android:layout_width="60dp"
android:layout_height="22dp"
android:background="@color/color_2D52E3"
android:text="人员分组"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
<Button
android:id="@+id/btn_remove"
android:layout_width="60dp"
android:layout_height="22dp"
android:background="@color/color_2D52E3"
android:text="移除"
android:textColor="@color/white"
android:textSize="@dimen/text_10"
android:layout_alignParentRight="true"
android:visibility="gone"
android:layout_centerVertical="true"/>
</RelativeLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fcv_group_people"
android:layout_width="924dp"
android:layout_height="422dp"
android:layout_marginTop="16dp"
android:background="@drawable/bg_shape"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_marginTop="10dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout_groups"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:tabIndicator="@null"
app:tabSelectedTextColor="@color/color_0287F9"
app:tabTextColor="@color/white"
app:tabMaxWidth="0dp"
app:tabPaddingStart="0dp"
app:tabPaddingEnd="28dp"
app:tabMode="fixed"
app:tabTextAppearance="@style/tabLayout"/>
<androidx.viewpager.widget.ViewPager
android:id="@+id/vp_pager"
android:layout_marginTop="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="never"/>
<!--<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_text_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/select_text_2"
android:textSize="@dimen/text_11"
android:text="@string/select_one"
android:layout_marginRight="28dp"/>
<TextView
android:id="@+id/tv_text_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/select_text_2"
android:textSize="@dimen/text_11"
android:text="@string/select_two"
android:layout_marginRight="28dp"/>
<TextView
android:id="@+id/tv_text_three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/select_text_2"
android:textSize="@dimen/text_11"
android:text="@string/select_three"
android:layout_marginRight="28dp"/>
<TextView
android:id="@+id/tv_text_four"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/select_text_2"
android:textSize="@dimen/text_11"
android:text="@string/select_four"
android:layout_marginRight="28dp"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_group_list"
android:layout_marginTop="22dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>-->
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_marginTop="30dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_no_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_tab_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="31dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
android:singleLine="true"
android:textSize="@dimen/text_10"
android:textColor="@color/white"
android:text=""
android:gravity="center|left"/>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/dash_line_shape"
android:layerType="software"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_item"
android:layout_width="140dp"
android:layout_height="96dp"
android:layout_marginRight="14.5dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_12_5"
android:textColor="@color/white"
android:layout_marginTop="10.5dp"
android:layout_marginLeft="12dp"/>
<EditText
android:id="@+id/et_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:layout_centerHorizontal="true"
android:textColor="@color/white"
android:textSize="@dimen/text_35"
android:background="@null"
android:outlineProvider="none"
android:textStyle="bold"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="31dp"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="0dp"
android:singleLine="true"
android:textSize="@dimen/text_10"
android:textColor="@color/white"
android:text=""
android:gravity="center|right"/>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:background="@drawable/dash_line_shape"
android:layerType="software"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:id="@+id/ll_item"
android:layout_marginRight="40dp">
<TextView
android:id="@+id/tv_person_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_10"
android:textColor="@color/white"
android:gravity="center"
android:text=""
android:drawableLeft="@drawable/select_one"
android:drawablePadding="7dp"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="939.59dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="15dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/banner_top"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/top_time"
android:textColor="@color/color_BDE4FF"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:gravity="center|left"
android:layout_alignParentRight="true"
android:layout_marginRight="96dp"
android:layout_marginTop="4dp"
android:textSize="@dimen/time_size"/>
</RelativeLayout>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_item"
android:layout_width="140dp"
android:layout_height="96dp"
android:layout_marginRight="14.5dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_12_5"
android:textColor="@color/white"
android:layout_marginTop="10.5dp"
android:layout_marginLeft="12dp"/>
<EditText
android:id="@+id/et_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
android:layout_centerHorizontal="true"
android:textColor="@color/white"
android:textSize="@dimen/text_35"
android:background="@null"
android:outlineProvider="none"
android:textStyle="bold"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_item"
android:layout_width="101.45dp"
android:layout_height="101.45dp"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_centerInParent="true">
<TextView
android:id="@+id/tv_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textStyle="bold"
android:textSize="@dimen/text_24_5"
android:text=""
/>
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="@dimen/text_9"
android:text=""/>
</LinearLayout>
</RelativeLayout>
\ No newline at end of file
<?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>
\ No newline at end of file
<?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>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.StatInfo" 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">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
\ No newline at end of file
<?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>
<color name="grey">#888888</color>
<color name="red">#ff0000</color>
<color name="orange_light">#ffffdd</color>
<color name="transparent">#00000000</color>
<color name="blue">#0099ff</color>
<color name="green">#00ff99</color>
<color name="bg_070A2E">#070A2E</color>
<color name="bg_060A38">#060A38</color>
<color name="color_038BFF">#038BFF</color>
<color name="color_2D52E3">#2D52E3</color>
<color name="color_694BFF">#694BFF</color>
<color name="color_8A34D5">#8A34D5</color>
<color name="color_00A89C">#00A89C</color>
<color name="color_BDE4FF">#BDE4FF</color>
<color name="color_0090FF">#0090FF</color>
<color name="color_206ED4">#206ED4</color>
<color name="color_656B72">#656B72</color>
<color name="color_0287F9">#0287F9</color>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="time_size">10sp</dimen>
<dimen name="text_10">10sp</dimen>
<dimen name="text_12_5">12.5sp</dimen>
<dimen name="text_35">35sp</dimen>
<dimen name="text_24_5">24.5sp</dimen>
<dimen name="text_9">9sp</dimen>
<dimen name="text_25">25sp</dimen>
<dimen name="text_13">13sp</dimen>
<dimen name="text_15">15sp</dimen>
<dimen name="text_11">11sp</dimen>
<dimen name="dlg_margin">10dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">StatInfo</string>
<string name="text_01">分组情况</string>
<string name="text_02">人员情况</string>
<string name="text_03">进出情况</string>
<string name="select_one">防水班组</string>
<string name="select_two">外架班组</string>
<string name="select_three">工地班组</string>
<string name="select_four">监理单位</string>
<string name="top_time">人员管理展示平台</string>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="select">
<item name="android:textSize">12sp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:textColor">@color/black</item>
<item name="android:background">@null</item>
<item name="android:button">@null</item>
<item name="android:drawableLeft">@drawable/check_one</item>
<item name="android:drawablePadding">5dp</item>
<item name="android:layout_marginRight">25dp</item>
</style>
<style name="tabLayout">
<item name="android:textSize">11sp</item>
</style>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.StatInfo" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/white</item>
<item name="colorPrimaryVariant">@color/transparent</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/teal_200</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 如果不设置root,将会发生“Failed to find configured root that contains...”错误 -->
<root-path name="root_path" path="."/>
<external-path name="autoupdate" path="download/" />
</paths>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="." />
</paths>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--android10 网络请求 需要加上这个-->
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
\ No newline at end of file
package com.srthinker.statinfo;
import com.alibaba.fastjson.JSONObject;
import com.srthinker.statinfo.api.kuangshi.MyWebSocketClient;
import com.srthinker.statinfo.api.kuangshi.api.auth.AuthApi;
import com.srthinker.statinfo.api.kuangshi.api.auth.bean.LoginResp;
import com.srthinker.statinfo.api.kuangshi.api.auth.impl.AuthApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.device.DeviceApi;
import com.srthinker.statinfo.api.kuangshi.api.device.bean.DeviceStatusResp;
import com.srthinker.statinfo.api.kuangshi.api.device.impl.DeviceApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.group.GroupApi;
import com.srthinker.statinfo.api.kuangshi.api.group.impl.GroupApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.person.PersonApi;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.FaceListItem;
import com.srthinker.statinfo.api.kuangshi.api.person.bean.PersonBean;
import com.srthinker.statinfo.api.kuangshi.api.person.impl.PersonApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.schedule.ScheduleApi;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleJsonBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleListRuleCrondBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.bean.ScheduleListRuleJsonBean;
import com.srthinker.statinfo.api.kuangshi.api.schedule.impl.ScheduleApiImpl;
import com.srthinker.statinfo.api.kuangshi.api.subscribe.SubscribeApi;
import com.srthinker.statinfo.api.kuangshi.api.subscribe.impl.SubscribeApiImpl;
import com.srthinker.statinfo.api.kuangshi.client.DefaultApiClient;
import com.srthinker.statinfo.api.kuangshi.utils.DigestUtils;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ApiDemo {
public static void main(String[] args) throws Exception {
String username = "admin";
//TODO 请替换下面的设备ip & 登录密码
String serverIp = "192.168.1.104";
String password = "admin123456";
String apiServerUrlPrefix = "http://" + serverIp;
//以设备为单位,每个设备都需要创建单独的DefaultApiClient
DefaultApiClient apiClient = new DefaultApiClient(apiServerUrlPrefix);
//一个设备创建的api,都应该用同一个apiClient
AuthApi authApi = new AuthApiImpl(apiClient);
DeviceApi deviceApi = new DeviceApiImpl(apiClient);
ScheduleApi scheduleApi = new ScheduleApiImpl(apiClient);
PersonApi personApi = new PersonApiImpl(apiClient);
GroupApi groupApi = new GroupApiImpl(apiClient);
SubscribeApi subscribeApi = new SubscribeApiImpl(apiClient);
//进行设备登录
// LoginResp loginResp = authApi.login("admin", "a12345");
LoginResp loginResp = authApi.login(username, password);
if(loginResp.getStatus() != 200) {
//登录出错,打印错误信息
System.out.println(JSONObject.toJSONString(loginResp));
return;
}
//获取设备状态
DeviceStatusResp deviceStatusResp = deviceApi.status();
System.out.println(JSONObject.toJSONString(deviceStatusResp));
// //添加门禁计划 - 通过json格式添加
// ScheduleJsonBean scheduleBeanJson = mockScheduleByJson();
// scheduleBeanJson = scheduleApi.addScheduleItemByJson(scheduleBeanJson);
// System.out.println(JSONObject.toJSONString(scheduleBeanJson));
// //添加门禁计划 - 通过crond格式添加
// ScheduleCrondBean scheduleBeanCrond = mockScheduleByCrond();
// scheduleBeanCrond = scheduleApi.addScheduleItemByCrond(scheduleBeanCrond);
// System.out.println(JSONObject.toJSONString(scheduleBeanCrond));
// //添加人员组
// GroupBean groupBean = new GroupBean();
// groupBean.setGroupName("组名称_" + System.currentTimeMillis());
// groupBean.setScheduleId(scheduleBeanCrond.getId());
// groupBean = groupApi.add(groupBean);
// //添加人员
// PersonBean personBean = mockPerson(loginResp.getSessionId(), groupBean.getId());
// personApi.add(personBean);
//HTTP上传文件升级
// File file = new File("/Users/liuqingliang/Downloads/test_img.jpeg");
// FirmwareBean firmwareBean = deviceApi.firmware(file);
// System.out.println(JSONObject.toJSONString(firmwareBean));
// //OTA升级接口
// FirmwareBean fb = deviceApi.firmwareOta("http://xxxxxx/xxxx.bin", "");
// System.out.println(JSONObject.toJSONString(fb));
//设置第三方服务器推送配置
// subscribeApi.push("http://xxxxxxx:8080/xxxx", true, "POST");
//开始websocket client, 进行消息订阅
Map<String, String> headers = new HashMap<>();
String wsServerUrl = String.format("ws://%s%s?session_id=%s", serverIp, "/api/subscribe", loginResp.getSessionId());
System.out.println(wsServerUrl);
MyWebSocketClient myWebSocketClient = new MyWebSocketClient(wsServerUrl);
// myWebSocketClient.send("hello");
Thread.sleep(600000);
}
public static PersonBean mockPerson(String sessionId, String groupId) {
PersonBean personBean = new PersonBean();
personBean.setRecognitionType("visitor");
personBean.setPersonName("人员姓名_" + System.currentTimeMillis());
personBean.setPasswordEncryptType("plain");
//TODO 加密的demo
// personBean.setPassword(DigestUtils.aesEncrypt("123456", sessionId));
personBean.setPassword("123456");
personBean.setIdNumber(DigestUtils.aesEncrypt("321345454", sessionId));
personBean.setCardNumber("cn" + (System.currentTimeMillis() % 10000));
personBean.setGroupList(Arrays.asList(new String[]{groupId}));
//获取图片
FaceListItem flt = new FaceListItem(0, getImageData("/Users/liuqingliang/Downloads/test_img.jpeg"));
personBean.setFaceList(Arrays.asList(flt));
personBean.setVisitBeginTime(new Date().toString());
personBean.setVisitEndTime(new Date(System.currentTimeMillis() + 100000).toString());
return personBean;
}
public static String getImageData(String filePath) {
try {
byte[] cb = new byte[0];
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
cb = Files.readAllBytes(Paths.get(filePath));
}
String content = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
content = new String( Base64.getEncoder().encodeToString(cb));
}
return content;
} catch (Exception e) {
throw new RuntimeException("");
}
}
public static ScheduleCrondBean mockScheduleByCrond() {
ScheduleCrondBean scheduleBean = new ScheduleCrondBean();
scheduleBean.setScheduleName("JSON时间计划_" + System.currentTimeMillis());
scheduleBean.setScheduleListType("crond");
List<ScheduleListRuleCrondBean> scheduleList = new ArrayList<>();
ScheduleListRuleCrondBean scheduleListRuleCrondBean = new ScheduleListRuleCrondBean();
scheduleListRuleCrondBean.setType("workday");
scheduleListRuleCrondBean.setRule("8:00-21:00,21:00-22:00 * * 1 *");
scheduleList.add(scheduleListRuleCrondBean);
scheduleListRuleCrondBean = new ScheduleListRuleCrondBean();
scheduleListRuleCrondBean.setType("holiday");
scheduleListRuleCrondBean.setRule("8:00-21:00,21:00-22:00 9 10 * *");
scheduleList.add(scheduleListRuleCrondBean);
scheduleBean.setScheduleList(scheduleList);
return scheduleBean;
}
public static ScheduleJsonBean mockScheduleByJson() {
ScheduleJsonBean scheduleBean = new ScheduleJsonBean();
scheduleBean.setScheduleName("JSON时间计划_" + System.currentTimeMillis());
scheduleBean.setScheduleListType("json");
List<ScheduleListRuleJsonBean> scheduleList = new ArrayList<>();
ScheduleListRuleJsonBean scheduleListRuleJsonBean = new ScheduleListRuleJsonBean();
scheduleListRuleJsonBean.setType("workday");
HashMap<String, String> rules = new HashMap<>();
rules.put("1", "00:02-11:59,14:00-23:59");
rules.put("2", "00:20-03:20,08:00-16:59,17:00-23:59");
rules.put("3", "09:20-16:20");
rules.put("4", "09:20-16:20");
rules.put("5", "09:20-16:20");
rules.put("6", "09:20-16:20");
rules.put("7", "09:20-16:20");
scheduleListRuleJsonBean.setRule(rules);
scheduleList.add(scheduleListRuleJsonBean);
scheduleListRuleJsonBean = new ScheduleListRuleJsonBean();
scheduleListRuleJsonBean.setType("holiday");
rules = new HashMap<>();
rules.put("20210330", "00:02-11:59,14:00-23:59");
rules.put("20210403", "09:20-16:20");
scheduleListRuleJsonBean.setRule(rules);
scheduleList.add(scheduleListRuleJsonBean);
scheduleBean.setScheduleList(scheduleList);
return scheduleBean;
}
}
package com.srthinker.statinfo;
import com.srthinker.statinfo.util.common.DateUtil;
import org.junit.Test;
import java.util.Date;
public class DateTest {
@Test
public void dateTest(){
String DEFAULT_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";
String nowDateTime = DateUtil.getNowDateTime();
System.out.println("当前时间:" + nowDateTime);
/* Date currentDate = new Date();
String localZoneFormattedDateTime = DateUtil.toLocalZoneFormattedDateTime(currentDate, DEFAULT_FORMAT);
System.out.println("当前时间(本地时区格式):" + localZoneFormattedDateTime);
String dateTimeString = "2023-07-24T19:39:28+08:00";
Date parsedDateTime = null;
parsedDateTime = DateUtil.parseDateTime(dateTimeString, DEFAULT_FORMAT);
String utcFormattedDateTime = DateUtil.getFormattedDateTime(parsedDateTime, DEFAULT_FORMAT);
System.out.println("解析后的日期时间(UTC格式):" + utcFormattedDateTime);
String localZoneFormattedDateTime2 = DateUtil.toLocalZoneFormattedDateTime(parsedDateTime, DEFAULT_FORMAT);
System.out.println("转换后的日期时间(本地时区格式):" + localZoneFormattedDateTime2);*/
/*String formattedDateTime = DateUtil.getFormattedDateTime(new Date(), "yyyy-MM-dd");
System.out.println(formattedDateTime);
Date date = DateUtil.parseDateTime(formattedDateTime, "yyyy-MM-dd");
String localZoneFormattedDateTime3 = DateUtil.toLocalZoneFormattedDateTime(date, DEFAULT_FORMAT);
System.out.println(localZoneFormattedDateTime3);*/
String nowDateFormattedZone = DateUtil.getDateFormattedZone(new Date(), "yyyy-MM-dd");
System.out.println(nowDateFormattedZone);
String dateFormattedZone = DateUtil.getDateFormattedZone(DateUtil.getNextDate(), "yyyy-MM-dd");
System.out.println(dateFormattedZone);
String zoneToDateString = DateUtil.zoneToDateString(nowDateFormattedZone, "HH:mm");
System.out.println(zoneToDateString);
}
}
package com.srthinker.statinfo;
import com.srthinker.statinfo.bean.ConfigBean;
import com.srthinker.statinfo.database.entity.ConfigEntity;
import com.srthinker.statinfo.database.entity.PersonEntity;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class EqualTest {
@Test
public void repeatTest(){
List<PersonEntity> allPersonList = new ArrayList<>();
List<PersonEntity> personEntities = new ArrayList<>();
List<PersonEntity> personEntities1 = new ArrayList<>();
PersonEntity personEntity = new PersonEntity();
personEntity.setId("1");
personEntity.setPerson_name("chen");
personEntity.setTimestamp("17:00");
PersonEntity personEntity2 = new PersonEntity();
personEntity2.setId("1");
personEntity2.setPerson_name("chen");
personEntity2.setTimestamp("17:00");
personEntities.add(personEntity);
personEntities1.add(personEntity2);
allPersonList.addAll(personEntities);
allPersonList.addAll(personEntities1);
Set<PersonEntity> mergeSet = new LinkedHashSet<>(allPersonList);
allPersonList = new ArrayList<>(mergeSet);
for (PersonEntity entity : allPersonList) {
System.out.println("遍历:name="+entity.getPerson_name());
}
}
@Test
public void configTest(){
List<ConfigBean> allConfigList = new ArrayList<>();
List<ConfigBean> configBeanList = new ArrayList<>();
ConfigBean configBean = new ConfigBean();
configBean.setUsername("admin");
configBean.setServerIp("111");
ConfigBean configBean1 = new ConfigBean();
configBean1.setUsername("admin");
configBean1.setServerIp("111");
configBeanList.add(configBean);
configBeanList.add(configBean1);
allConfigList.addAll(configBeanList);
/*LinkedHashSet<ConfigBean> linkedHashSet = new LinkedHashSet<>(allConfigList);
allConfigList = new ArrayList<>(linkedHashSet);*/
for (ConfigBean bean : allConfigList) {
System.out.println("遍历bean的:name="+bean.getUsername());
}
}
@Test
public void configTest1(){
List<ConfigEntity> configList1 = new ArrayList<>();
List<ConfigEntity> configList2 = new ArrayList<>();
ConfigEntity configBean = new ConfigEntity();
configBean.setUsername("admin");
configBean.setServerIp("111");
ConfigEntity configBean1 = new ConfigEntity();
configBean1.setUsername("admin");
configBean1.setServerIp("111");
configList1.add(configBean);
configList2.add(configBean1);
System.out.println("是否相等="+configList1.equals(configList2));
}
}
package com.srthinker.statinfo;
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);
}
}
\ No newline at end of file
package com.srthinker.statinfo;
import com.srthinker.statinfo.database.entity.PersonEntity;
import com.srthinker.statinfo.presenter.StatSize;
import com.srthinker.statinfo.util.common.DateUtil;
import com.srthinker.statinfo.util.common.Utils;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class UtilTest {
/*@Test
public void noRepet(){
List<PersonEntity> personEntities = new ArrayList<>();
for (int i = 0; i < 4; i++) {
PersonEntity person = new PersonEntity();
person.setId("1");
person.setPerson_name("王大崔");
person.setTimestamp("11:0"+i);
personEntities.add(person);
}
for (PersonEntity personEntity : personEntities) {
System.out.println("去重前:id="+personEntity.getId()+" name="+personEntity.getPerson_name()+" time="+personEntity.getTimestamp());
}
List<PersonEntity> personEntities2 = Utils.reverseList(personEntities);
List<PersonEntity> personEntities1 = Utils.removeDuplicates(personEntities2, "id");
for (PersonEntity personEntity : personEntities1) {
System.out.println("去重后:id="+personEntity.getId()+" name="+personEntity.getPerson_name()+" time="+personEntity.getTimestamp());
}
}*/
@Test
public void filter(){
List<PersonEntity> personEntities = new ArrayList<>();
for (int i = 0; i < 4; i++) {
PersonEntity person = new PersonEntity();
person.setId("1");
person.setPerson_name("王大崔");
person.setTimestamp("11:0"+0);
if (i==3){
person.setTimestamp("11:0"+i);
}
personEntities.add(person);
}
for (PersonEntity personEntity : personEntities) {
System.out.println("去重前:id="+personEntity.getId()+" name="+personEntity.getPerson_name()+" time="+personEntity.getTimestamp());
}
List<PersonEntity> personEntities2 = Utils.reverseList(personEntities);
List<PersonEntity> personEntities1 = StatSize.filterList(personEntities2);
for (PersonEntity personEntity : personEntities1) {
System.out.println("去重后:id="+personEntity.getId()+" name="+personEntity.getPerson_name()+" time="+personEntity.getTimestamp());
}
}
@Test
public void getDiffer(){
long timeDifference = DateUtil.getTimeDifference("HH:mm", "", "10:01");
System.out.println("相差为"+timeDifference);
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
\ No newline at end of file
# 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
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.enableJetifier=true
\ No newline at end of file
#Mon Jul 17 17:17:49 CST 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## 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='"-Xmx64m" "-Xms64m"'
# 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 or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@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 Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@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="-Xmx64m" "-Xms64m"
@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 execute
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 execute
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
: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 %*
: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
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}
rootProject.name = "StatInfo"
include ':app'
File added
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment