修改偶现bug: 步骤如下: 1. 点击开始测试按钮,数据上报正常; 2. 点击结束检测按钮,弹出保存数据对话框; 3. 点击取消按钮。 4. 再次从过程1开始测试,出现无法识别的ID; 原因: 经过分析日志发现,再次点击测试的时候串口上报的数据没有正确处理,问题出现在串口适配层。 当2、3、4三个动作中间没有任何停留世间操作非常快的时候,这个问题成为必现问题,即使第3个 步骤点击保存按钮,再迅速操作第4个步骤也会出现问题。由这个现象进行分析,确定是由于操作 太快,此时串口并没有正常的关闭,就开始了下一个测试流程。 修改: 该问题有好几种修改方法,经过各方面权衡,采用一种最稳妥对于当前流程逻辑影响最小的方法: 1. 在保存数据对话框点击取消以后弹出一个“正在取消”的模态框,时间为8秒。 2. 延长“正在保存”对话框的时间为8秒。 */master
| @ -0,0 +1,18 @@ | |||
| *.iml | |||
| .gradle | |||
| /local.properties | |||
| /.idea/libraries | |||
| /.idea/modules.xml | |||
| /.idea/workspace.xml | |||
| .DS_Store | |||
| /build | |||
| /captures | |||
| .externalNativeBuild | |||
| .idea | |||
| .idea/ | |||
| app/libs/ | |||
| serialportlib/libs/ | |||
| serialportlib/src/main/res/drawable/ | |||
| !app-release.apk | |||
| @ -0,0 +1,5 @@ | |||
| ## HANDSET-JE002-EX | |||
| ### 说明 | |||
| 传感器通过串口上报响应的检测数据:温度、湿度、内压、外压 | |||
| @ -0,0 +1 @@ | |||
| /build | |||
| @ -0,0 +1,74 @@ | |||
| apply plugin: 'com.android.application' | |||
| android { | |||
| compileSdkVersion 27 | |||
| defaultConfig { | |||
| applicationId "com.handset.serialportsensor" | |||
| minSdkVersion 19 | |||
| targetSdkVersion 27 | |||
| versionCode 1 | |||
| versionName "2.3" | |||
| testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | |||
| compileOptions { | |||
| sourceCompatibility JavaVersion.VERSION_1_8 | |||
| targetCompatibility JavaVersion.VERSION_1_8 | |||
| } | |||
| javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } | |||
| multiDexEnabled true | |||
| } | |||
| buildTypes { | |||
| release { | |||
| minifyEnabled false | |||
| proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |||
| } | |||
| } | |||
| lintOptions { | |||
| checkReleaseBuilds false | |||
| abortOnError false | |||
| } | |||
| applicationVariants.all { variant -> | |||
| variant.outputs.all { output -> | |||
| def outputFile = output.outputFile | |||
| if (outputFile != null && outputFile.name.endsWith('.apk')) { | |||
| //版本名-版本号-发布时间.apk | |||
| def fileName = "检测仪_JE002_EX_V${versionName}_${releaseTime()}.apk" | |||
| outputFileName = fileName | |||
| } | |||
| } | |||
| } | |||
| } | |||
| dependencies { | |||
| implementation fileTree(include: ['*.jar'], dir: 'libs') | |||
| implementation rootProject.ext.deps.appcompatV7 | |||
| implementation rootProject.ext.deps.recyclerviewV7 | |||
| implementation rootProject.ext.deps.constraintLayout | |||
| implementation rootProject.ext.deps.rvAdapterHelper | |||
| implementation rootProject.ext.deps.rvDivider | |||
| implementation rootProject.ext.deps.stickyDecoration | |||
| implementation rootProject.ext.deps.utils | |||
| implementation rootProject.ext.deps.jodaTime | |||
| implementation rootProject.ext.deps.rxJava | |||
| implementation rootProject.ext.deps.rxAndroid | |||
| implementation 'com.android.support.constraint:constraint-layout:1.1.0' | |||
| implementation 'com.android.support:support-v4:27.1.1' | |||
| implementation 'com.android.support:design:27.1.1' | |||
| implementation 'org.projectlombok:lombok:1.16.16' | |||
| annotationProcessor "org.projectlombok:lombok:1.16.16" | |||
| compileOnly 'org.glassfish:javax.annotation:10.0-b28' | |||
| implementation 'com.squareup.retrofit2:converter-gson:2.2.0' | |||
| implementation project(':serialportlib') | |||
| implementation 'com.github.suntiago:dblib:v1.0-beta' | |||
| implementation 'com.android.support:multidex:1.0.3' | |||
| implementation 'cn.jingzhuan.lib:chart:0.10.17@aar' | |||
| implementation 'com.google.guava:guava:22.0-android' | |||
| } | |||
| def static releaseTime() { | |||
| return new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+8")) | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| # Add project specific ProGuard rules here. | |||
| # You can control the set of applied configuration files using the | |||
| # proguardFiles setting in build.gradle. | |||
| # | |||
| # For more details, see | |||
| # http://developer.android.com/guide/developing/tools/proguard.html | |||
| # If your project uses WebView with JS, uncomment the following | |||
| # and specify the fully qualified class name to the JavaScript interface | |||
| # class: | |||
| #-keepclassmembers class fqcn.of.javascript.interface.for.webview { | |||
| # public *; | |||
| #} | |||
| # Uncomment this to preserve the line number information for | |||
| # debugging stack traces. | |||
| #-keepattributes SourceFile,LineNumberTable | |||
| # If you keep the line number information, uncomment this to | |||
| # hide the original source file name. | |||
| #-renamesourcefileattribute SourceFile | |||
| @ -0,0 +1 @@ | |||
| [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] | |||
| @ -0,0 +1,62 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
| package="com.handset.serialportsensor"> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> | |||
| <!--开机自启动权限--> | |||
| <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | |||
| <application | |||
| android:name="com.handset.serialportsensor.App" | |||
| android:allowBackup="true" | |||
| android:icon="@drawable/ic_launcher_c" | |||
| android:label="@string/app_name" | |||
| android:supportsRtl="true" | |||
| android:theme="@style/DefAppTheme"> | |||
| <activity | |||
| android:name="com.handset.serialportsensor.activity.SplashActivity" | |||
| android:screenOrientation="portrait" | |||
| android:theme="@style/SplashTheme"> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.MAIN" /> | |||
| <action android:name="android.intent.action.VIEW" /> | |||
| <category android:name="android.intent.category.LAUNCHER" /> | |||
| </intent-filter> | |||
| </activity> | |||
| <activity | |||
| android:name="com.handset.serialportsensor.activity.Main2Activity" | |||
| android:label="@string/title_activity_main" | |||
| android:screenOrientation="portrait" | |||
| android:theme="@style/DefAppTheme" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.HistoryActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.HistoryDetailActivity" /> | |||
| <activity | |||
| android:name="com.handset.serialportsensor.activity.LoginActivity" | |||
| android:launchMode="singleTask" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.SensorSettingsActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.BaudRateSettingActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ThresholdActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ConeSettingActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.DataRecoverActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.PasswordResetActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ThirdSensorSettingsActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ChangeSensorIdSettingsActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ViewOperateLogListActivity" /> | |||
| <activity android:name="com.handset.serialportsensor.activity.ViewLogActivity" /> | |||
| <receiver | |||
| android:name="com.handset.serialportsensor.BootReceiver" | |||
| android:enabled="true" | |||
| android:exported="true" | |||
| android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> | |||
| <intent-filter> | |||
| <action android:name="android.intent.action.BOOT_COMPLETED" /> | |||
| <category android:name="android.intent.category.DEFAULT" /> | |||
| </intent-filter> | |||
| </receiver> | |||
| </application> | |||
| </manifest> | |||
| @ -0,0 +1,44 @@ | |||
| package com.handset.serialportsensor; | |||
| import android.support.multidex.MultiDexApplication; | |||
| import com.blankj.utilcode.util.Utils; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.db.DBUpdateHelperMY; | |||
| import com.handset.serialportsensor.utils.CrashHandler; | |||
| import com.handset.serialportsensor.utils.PersistHelper; | |||
| import com.handset.serialportsensor.utils.Slog; | |||
| import net.danlew.android.joda.JodaTimeAndroid; | |||
| import org.kymjs.kjframe.KJDB; | |||
| public class App extends MultiDexApplication { | |||
| static boolean debug = BuildConfig.DEBUG; | |||
| @Override | |||
| public void onCreate() { | |||
| super.onCreate(); | |||
| Utils.init(this); | |||
| JodaTimeAndroid.init(this); | |||
| Slog.init(this); | |||
| Slog.setDebug(true, true); | |||
| Slog.enableSaveLog(true); | |||
| KJDB.create(this, "htjc_sensor_history.db", !debug, DBUpdateHelperMY.DATABASE_VERSION, new DBUpdateHelperMY()); | |||
| /* | |||
| * 初始化账户组件,不使用自动登录 | |||
| * */ | |||
| AccountManager.init((this), debug); | |||
| //保存Crash的Log | |||
| CrashHandler crashHandler = CrashHandler.getInstance(); | |||
| crashHandler.init(getApplicationContext()); | |||
| PersistHelper.init((this)); | |||
| } | |||
| } | |||
| @ -0,0 +1,24 @@ | |||
| package com.handset.serialportsensor; | |||
| import android.content.BroadcastReceiver; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import com.handset.serialportsensor.activity.Main2Activity; | |||
| import com.handset.serialportsensor.utils.Slog; | |||
| public class BootReceiver extends BroadcastReceiver { | |||
| private final String TAG = getClass().getSimpleName(); | |||
| @Override | |||
| public void onReceive(Context context, Intent intent) { | |||
| if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { | |||
| Slog.d(TAG, "Receive Broadcast"); | |||
| Intent bootIntent = new Intent(context, Main2Activity.class); | |||
| bootIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |||
| context.startActivity(bootIntent); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,11 @@ | |||
| package com.handset.serialportsensor.account; | |||
| /** | |||
| * Created by Jeremy on 2018/8/2. | |||
| */ | |||
| public class Account { | |||
| //账户id | |||
| public String userId; | |||
| public String token; | |||
| } | |||
| @ -0,0 +1,169 @@ | |||
| package com.handset.serialportsensor.account; | |||
| import android.content.Context; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import com.handset.serialportsensor.utils.SPUtils; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| /** | |||
| * Created by Jeremy on 2018/8/2. | |||
| * 账户管理应用,适用于单用户系统 | |||
| */ | |||
| @SuppressWarnings(value = "unused") | |||
| public class AccountManager { | |||
| private final String TAG = getClass().getSimpleName(); | |||
| private static String AccountManager_user_id = "AccountManager_user_id"; | |||
| private static String AccountManager_account_token = "AccountManager_account_token"; | |||
| private static AccountManager sAccountManager; | |||
| private Context sContext; | |||
| //账户ID | |||
| private Account mAccount; | |||
| private List<AccountStatusCallback> mAccountStatusCallbacks = new ArrayList<>(); | |||
| private HashMap<AccountStatusCallback, List<String>> mCallbackListHashMap = new HashMap<>(); | |||
| public static AccountManager get() { | |||
| if (sAccountManager == null) { | |||
| throw new NullPointerException("please init AccountManager first before getting"); | |||
| } | |||
| return sAccountManager; | |||
| } | |||
| private AccountManager(Context sContext, boolean autoLogin) { | |||
| this.sContext = sContext; | |||
| if (autoLogin) { | |||
| autoLogin(); | |||
| } | |||
| } | |||
| public static void init(Context context) { | |||
| init(context, false); | |||
| } | |||
| public static void init(Context context, boolean autoLogin) { | |||
| if (sAccountManager == null) { | |||
| sAccountManager = new AccountManager(context, autoLogin); | |||
| } | |||
| } | |||
| public boolean isLogin() { | |||
| Log.i(TAG, "mAccount.userId: " + mAccount.userId); | |||
| return mAccount != null && !TextUtils.isEmpty(mAccount.userId); | |||
| } | |||
| public String getUserData(String key) { | |||
| if (isLogin()) { | |||
| return SPUtils.getInstance(sContext).get(mAccount.userId + key); | |||
| } | |||
| return null; | |||
| } | |||
| public void putUserData(String key, String data) { | |||
| Log.d(TAG, "putUserData [key, data]:" + key + " " + data); | |||
| if (isLogin()) { | |||
| SPUtils.getInstance(sContext).put(mAccount.userId + key, data); | |||
| if (mAccountStatusCallbacks.size() > 0) { | |||
| for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { | |||
| if (mCallbackListHashMap.containsKey(accountStatusCallback)) { | |||
| for (String s : mCallbackListHashMap.get(accountStatusCallback)) { | |||
| if (key.equals(s)) { | |||
| accountStatusCallback.userInfoChange(key); | |||
| break; | |||
| } | |||
| } | |||
| } else { | |||
| accountStatusCallback.userInfoChange(key); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| public String getUserId() { | |||
| if (isLogin()) { | |||
| return mAccount.userId; | |||
| } | |||
| return ""; | |||
| } | |||
| public String getToken() { | |||
| return isLogin() ? mAccount.token : ""; | |||
| } | |||
| private void autoLogin() { | |||
| String account = "admin"/*SPUtils.getInstance(sContext).get(AccountManager_user_id)*/; | |||
| String token = SPUtils.getInstance(sContext).get(account + AccountManager_account_token); | |||
| setAccount(account, token); | |||
| } | |||
| public void login(String userId, String token) { | |||
| setAccount(userId, token); | |||
| Log.i(TAG, "login [userId, pwd]:" + userId + " " + token + ""); | |||
| } | |||
| public void logout() { | |||
| Log.i(TAG, "logout []:" + getUserId()); | |||
| setAccount("", ""); | |||
| } | |||
| private void setAccount(String userId, String token) { | |||
| if (mAccount == null) { | |||
| mAccount = new Account(); | |||
| } | |||
| mAccount.userId = userId; | |||
| mAccount.token = token; | |||
| SPUtils.getInstance(sContext).put(AccountManager_user_id, userId); | |||
| SPUtils.getInstance(sContext).put(userId + AccountManager_account_token, token); | |||
| if (mAccountStatusCallbacks.size() > 0) { | |||
| if (isLogin()) { | |||
| for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { | |||
| accountStatusCallback.loginCallback(); | |||
| } | |||
| } else { | |||
| for (AccountStatusCallback accountStatusCallback : mAccountStatusCallbacks) { | |||
| accountStatusCallback.logoutCallback(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /*初次注册,立即回调一下*/ | |||
| public void registerAccountStatusCallBack(AccountStatusCallback statusCallback) { | |||
| registerAccountStatusCallBack(statusCallback, null); | |||
| } | |||
| /*初次注册,立即回调一下*/ | |||
| /** | |||
| * @param statusCallback 回调参数 | |||
| * @param interestKeys 感兴趣的字段,默认回调所有的字段 | |||
| */ | |||
| private void registerAccountStatusCallBack(AccountStatusCallback statusCallback, List<String> interestKeys) { | |||
| if (!mAccountStatusCallbacks.contains(mAccountStatusCallbacks)) { | |||
| mAccountStatusCallbacks.add(statusCallback); | |||
| if (interestKeys != null && interestKeys.size() > 0) { | |||
| if (mCallbackListHashMap.containsKey(statusCallback)) { | |||
| mCallbackListHashMap.remove(statusCallback); | |||
| } | |||
| mCallbackListHashMap.put(statusCallback, interestKeys); | |||
| } | |||
| if (isLogin()) { | |||
| statusCallback.loginCallback(); | |||
| } else { | |||
| //statusCallback.logoutCallback(); | |||
| } | |||
| } | |||
| } | |||
| public void unregisterAccountStatusCallBack(AccountStatusCallback statusCallback) { | |||
| mAccountStatusCallbacks.remove(statusCallback); | |||
| mCallbackListHashMap.remove(statusCallback); | |||
| } | |||
| } | |||
| @ -0,0 +1,13 @@ | |||
| package com.handset.serialportsensor.account; | |||
| /** | |||
| * Created by Jeremy on 2018/8/2. | |||
| */ | |||
| public interface AccountStatusCallback { | |||
| void loginCallback(); | |||
| void logoutCallback(); | |||
| void userInfoChange(String key); | |||
| } | |||
| @ -0,0 +1,124 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.app.AlertDialog; | |||
| import android.os.Handler; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.util.Log; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| public abstract class BaseActivity extends AppCompatActivity { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private boolean mResume = false; | |||
| boolean mNeedToDismissProgressDlg = false; | |||
| boolean mNeedToShowProgressDlg = false; | |||
| AlertDialog mLoadingDialog; | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| this.mResume = true; | |||
| checkProgress(); | |||
| } | |||
| @Override | |||
| protected void onPause() { | |||
| this.mResume = false; | |||
| super.onPause(); | |||
| } | |||
| protected String genCmd(String sensorNo, int cmdId) { | |||
| try { | |||
| String content = sensorNo.concat("00" + Integer.toHexString(cmdId) + "00"); | |||
| return "DDDD" + content + CRCUtils.genCrc(content); | |||
| } catch (Exception e) { | |||
| Log.e(logTag, e.getMessage()); | |||
| return null; | |||
| } | |||
| } | |||
| public void showDialog(final AlertDialog loadingDialog) { | |||
| if (loadingDialog == null) { | |||
| return; | |||
| } | |||
| mLoadingDialog = loadingDialog; | |||
| if (mResume) { | |||
| mLoadingDialog.show(); | |||
| mNeedToShowProgressDlg = false; | |||
| } else { | |||
| mNeedToShowProgressDlg = true; | |||
| } | |||
| } | |||
| private void checkProgress() { | |||
| if (mLoadingDialog != null && mResume) { | |||
| if (mNeedToShowProgressDlg) { | |||
| mLoadingDialog.show(); | |||
| mNeedToShowProgressDlg = false; | |||
| } | |||
| if (mNeedToDismissProgressDlg) { | |||
| mLoadingDialog.dismiss(); | |||
| mNeedToDismissProgressDlg = false; | |||
| mLoadingDialog = null; | |||
| } | |||
| } | |||
| } | |||
| public void dismissDialog(final AlertDialog loadingDialog) { | |||
| if (loadingDialog == null && mLoadingDialog == null) { | |||
| return; | |||
| } | |||
| if (mResume) { | |||
| if (loadingDialog != null && loadingDialog.isShowing()) { | |||
| loadingDialog.dismiss(); | |||
| } else if (mLoadingDialog != null && mLoadingDialog.isShowing()) { | |||
| mLoadingDialog.dismiss(); | |||
| } | |||
| mNeedToDismissProgressDlg = false; | |||
| mLoadingDialog = null; | |||
| } else { | |||
| mLoadingDialog = loadingDialog; | |||
| mNeedToDismissProgressDlg = true; | |||
| } | |||
| } | |||
| public void disMissDialogDelay(final AlertDialog alertDialog, int delayMillis) { | |||
| new Handler().postDelayed(() -> dismissDialogD(alertDialog), delayMillis); | |||
| } | |||
| protected void dismissDialogD(final AlertDialog alertDialog) { | |||
| if (mLoadingDialog == null && alertDialog == null) { | |||
| return; | |||
| } | |||
| if (mLoadingDialog != null && alertDialog != null && mLoadingDialog == alertDialog) { | |||
| dismissDialog(alertDialog); | |||
| return; | |||
| } | |||
| if (mLoadingDialog == null) { | |||
| if (mResume && alertDialog.isShowing()) { | |||
| alertDialog.dismiss(); | |||
| } | |||
| } | |||
| } | |||
| public void disMissLoadingDialog(final AlertDialog loadingDialog) { | |||
| runOnUiThread(() -> { | |||
| /*if (loadingDialog != null && loadingDialog.isShowing()) { | |||
| loadingDialog.dismiss(); | |||
| }*/ | |||
| dismissDialog(loadingDialog); | |||
| }); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| super.onDestroy(); | |||
| } | |||
| } | |||
| @ -0,0 +1,265 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.annotation.SuppressLint; | |||
| import android.app.AlertDialog; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.os.Message; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.widget.ImageView; | |||
| import android.widget.RelativeLayout; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import java.util.Arrays; | |||
| public class BaudRateSettingActivity extends BaseActivity implements View.OnClickListener, SurfaceContract.ISerialView { | |||
| private final String logTag = "HANDSET-JE002-EX"; | |||
| private TextView tvBr9600; | |||
| private TextView tvBr19200; | |||
| private TextView tvNum3; | |||
| private ImageView ivBr9600; | |||
| private ImageView ivBr19200; | |||
| private ImageView ivBr38400; | |||
| private byte baudByte = 0x01; | |||
| private Integer baudRate; | |||
| private String sensorId; | |||
| private AlertDialog baudSettingsDialog; | |||
| private SurfacePresenter mPresenter = new SurfacePresenter((this)); | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_baudrate_setting); | |||
| Intent intent = getIntent(); | |||
| if (intent != null) { | |||
| baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); | |||
| sensorId = intent.getStringExtra(Constant.SENSOR_ID); | |||
| } | |||
| initView(); | |||
| } | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| } | |||
| @Override | |||
| protected void onPause() { | |||
| super.onPause(); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| mPresenter.close(); | |||
| super.onDestroy(); | |||
| } | |||
| private void initView() { | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| TextView tvConfirm = findViewById(R.id.tv_confirm); | |||
| RelativeLayout rlNum1 = findViewById(R.id.rl_br_9600); | |||
| RelativeLayout rlNum2 = findViewById(R.id.rl_br_19200); | |||
| RelativeLayout rlNum3 = findViewById(R.id.rl_br_38400); | |||
| tvBr9600 = findViewById(R.id.tv_br_9600); | |||
| tvBr19200 = findViewById(R.id.tv_br_19200); | |||
| tvNum3 = findViewById(R.id.tv_br_38400); | |||
| ivBr9600 = findViewById(R.id.iv_br_9600); | |||
| ivBr19200 = findViewById(R.id.iv_br_19200); | |||
| ivBr38400 = findViewById(R.id.iv_br_38400); | |||
| tvTitle.setText(R.string.baud_rate_setting); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| tvConfirm.setVisibility(View.VISIBLE); | |||
| tvConfirm.setText(R.string.confirm); | |||
| tvBr9600.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); | |||
| ivBr9600.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener(this); | |||
| tvConfirm.setOnClickListener(this); | |||
| rlNum1.setOnClickListener(this); | |||
| rlNum2.setOnClickListener(this); | |||
| rlNum3.setOnClickListener(this); | |||
| if (baudRate == 38400) { | |||
| clickId(R.id.rl_br_38400); | |||
| } else if (baudRate == 19200) { | |||
| clickId(R.id.rl_br_19200); | |||
| } else if (baudRate == 9600) { | |||
| clickId(R.id.rl_br_9600); | |||
| } | |||
| } | |||
| @Override | |||
| public void onClick(View view) { | |||
| clickId(view.getId()); | |||
| } | |||
| private void clickId(int id) { | |||
| switch (id) { | |||
| case R.id.title_back: | |||
| this.finish(); | |||
| break; | |||
| case R.id.tv_confirm: | |||
| if (ivBr9600.getVisibility() == View.VISIBLE) { | |||
| baudByte = 0x01; | |||
| } else if (ivBr19200.getVisibility() == View.VISIBLE) { | |||
| baudByte = 0x02; | |||
| } else { | |||
| baudByte = 0x03; | |||
| } | |||
| setBaudRate(); | |||
| break; | |||
| case R.id.rl_br_9600: | |||
| tvBr9600.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); | |||
| tvBr19200.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| tvNum3.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| ivBr9600.setVisibility(View.VISIBLE); | |||
| ivBr19200.setVisibility(View.GONE); | |||
| ivBr38400.setVisibility(View.GONE); | |||
| break; | |||
| case R.id.rl_br_19200: | |||
| tvBr9600.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| tvBr19200.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); | |||
| tvNum3.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| ivBr9600.setVisibility(View.GONE); | |||
| ivBr19200.setVisibility(View.VISIBLE); | |||
| ivBr38400.setVisibility(View.GONE); | |||
| break; | |||
| case R.id.rl_br_38400: | |||
| tvBr9600.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| tvBr19200.setTextColor(getResources().getColor(R.color.text_general_color)); | |||
| tvNum3.setTextColor(getResources().getColor(R.color.colorPrimaryDark)); | |||
| ivBr9600.setVisibility(View.GONE); | |||
| ivBr19200.setVisibility(View.GONE); | |||
| ivBr38400.setVisibility(View.VISIBLE); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| private void setBaudRate() { | |||
| Log.i(logTag, ("Setting BaudRate:" + baudRate)); | |||
| showSettingDialog(); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> mPresenter.open(baudRate), (300)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_3C, (3300)); | |||
| new Handler().postDelayed(() -> { | |||
| if (baudSettingsDialog != null && baudSettingsDialog.isShowing()) { | |||
| baudSettingsDialog.dismiss(); | |||
| setBaudFailed(); | |||
| } | |||
| }, (10000)); | |||
| } | |||
| @SuppressLint("HandlerLeak") | |||
| private Handler handler = new Handler() { | |||
| @Override | |||
| public void handleMessage(Message msg) { | |||
| super.handleMessage(msg); | |||
| if (msg.what == Constant.Command.COMMAND_3C) {//波特率设置 | |||
| Log.i(logTag, ("baud rate set: sensorId: " + sensorId)); | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| sb.append("00").append("3C").append("01").append("0".concat(String.valueOf(baudByte))); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(logTag, "baud rate set: cooked: " + cooked); | |||
| Log.i(logTag, "baud rate set: cooked 2: " + Arrays.toString(cooked.getBytes())); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } | |||
| }; | |||
| //正在设置波特率 | |||
| private void showSettingDialog() { | |||
| runOnUiThread(() -> baudSettingsDialog = ToastHelper.showTipDialog((BaudRateSettingActivity.this), R.mipmap.ic_setting, R.string.set_baud_rate_now_tips)); | |||
| } | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| if (rawData.getItemType() == RawData.TYPE_RECEIVE) { | |||
| String message = rawData.getMessage(); | |||
| Log.i(logTag, ("BaudRateSettingActivity, onSerialData: " + message)); | |||
| byte[] bytes = ByteUtils.hexStrToBytes(message); | |||
| if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_3D) { | |||
| mPresenter.close(); | |||
| if (baudSettingsDialog != null && baudSettingsDialog.isShowing()) { | |||
| baudSettingsDialog.dismiss(); | |||
| } | |||
| setBaudSuccess(); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| } | |||
| //波特率设置成功 | |||
| private void setBaudSuccess() { | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(baudSettingsDialog); | |||
| ToastHelper.showSubmitDialog( | |||
| getString(R.string.set_baud_rate_success), | |||
| R.mipmap.img_right, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.blue_button_bg), | |||
| getString(R.string.btn_ensure), BaudRateSettingActivity.this, | |||
| (View view) -> { | |||
| finish(); | |||
| Intent intent = new Intent((BaudRateSettingActivity.this), Main2Activity.class); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| startActivity(intent); | |||
| }); | |||
| }); | |||
| } | |||
| //波特率设置失败 | |||
| private void setBaudFailed() { | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(baudSettingsDialog); | |||
| ToastHelper.showSubmitDialog( | |||
| getString(R.string.set_baud_rate_failed), | |||
| R.mipmap.img_cross, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.button), | |||
| getString(R.string.btn_ensure), | |||
| (BaudRateSettingActivity.this), | |||
| (View view) -> finish() | |||
| ); | |||
| }); | |||
| } | |||
| } | |||
| @ -0,0 +1,192 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.annotation.SuppressLint; | |||
| import android.app.AlertDialog; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.os.Message; | |||
| import android.support.annotation.Nullable; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.widget.EditText; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import java.util.Arrays; | |||
| /** | |||
| * Created by zy on 2019/2/23. | |||
| */ | |||
| public class ChangeSensorIdSettingsActivity extends BaseActivity implements SurfaceContract.ISerialView { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private String sensorId; | |||
| private Integer baudRate; | |||
| private EditText etSensorId; | |||
| private SurfacePresenter mPresenter = new SurfacePresenter((this)); | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_change_sensor_id_setings); | |||
| Intent intent = getIntent(); | |||
| if (intent != null) { | |||
| sensorId = intent.getStringExtra(Constant.SENSOR_ID); | |||
| baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); | |||
| } | |||
| etSensorId = findViewById(R.id.et_sensor_id); | |||
| findViewById(R.id.btn_save).setOnClickListener((View v) -> save()); | |||
| initTitle(); | |||
| etSensorId.setText(sensorIdToInt(sensorId)); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| mPresenter.close(); | |||
| super.onDestroy(); | |||
| } | |||
| private String sensorIdToInt(String sensorId) { | |||
| byte[] bytes = ByteUtils.hexStrToBytes(sensorId); | |||
| Log.i(logTag, "sensorId hexStrToBytes: " + Arrays.toString(bytes)); | |||
| int no = ((bytes[0] & 0xff) * 100 + (bytes[1] & 0xff)) * 10000 + ((bytes[2] & 0xff) << 8) + (bytes[3] & 0xff); | |||
| String s = "00000000".concat(String.valueOf(no)); | |||
| return s.substring(s.length() - 8); | |||
| } | |||
| private void initTitle() { | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| tvTitle.setText(R.string.id_setting); | |||
| } | |||
| private void save() { | |||
| String sensorId = etSensorId.getText().toString(); | |||
| if (TextUtils.isEmpty(sensorId) || sensorId.length() != 8) { | |||
| Toast.makeText((this), R.string.id_must_8bits_tip, Toast.LENGTH_SHORT).show(); | |||
| } else { | |||
| boolean tagAccept = true; | |||
| for (int i = 0; i < 8; i++) { | |||
| char a = sensorId.charAt(i); | |||
| if (!from0to9(a)) { | |||
| Toast.makeText((this), R.string.id_must_8bits_tip, Toast.LENGTH_SHORT).show(); | |||
| tagAccept = false; | |||
| break; | |||
| } | |||
| } | |||
| if (tagAccept) { | |||
| showSettingDialog(); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_50, (3500)); | |||
| } | |||
| } | |||
| } | |||
| private AlertDialog settingsDialog; | |||
| private void showSettingDialog() { | |||
| runOnUiThread(() -> { | |||
| settingsDialog = ToastHelper.showTipDialog((ChangeSensorIdSettingsActivity.this), R.mipmap.ic_setting, R.string.id_setting_tip); | |||
| //disMissDialogDelay(settingsDialog, (10000)); | |||
| dismissSettingDialogDelay(); | |||
| } | |||
| ); | |||
| } | |||
| private Handler dismissHandler = new Handler(); | |||
| private Runnable dismissRunnable; | |||
| private void dismissSettingDialogDelay() { | |||
| dismissRunnable = () -> { | |||
| dismissDialogD(settingsDialog); | |||
| runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_fail, Toast.LENGTH_SHORT).show()); | |||
| }; | |||
| dismissHandler.postDelayed(dismissRunnable, (10000)); | |||
| } | |||
| @SuppressLint("HandlerLeak") | |||
| private Handler handler = new Handler() { | |||
| @Override | |||
| public void handleMessage(Message msg) { | |||
| super.handleMessage(msg); | |||
| if (msg.what == Constant.Command.COMMAND_50) {//设置传感器ID | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| byte[] bytes = ByteUtils.getByte4Id(etSensorId.getText().toString()); | |||
| String hexString = ByteUtils.bytesToHexStr(bytes); | |||
| Log.i(logTag, "sensor no set: sensor prior: " + Arrays.toString(bytes)); | |||
| Log.i(logTag, "sensor no set: hexString: " + hexString); | |||
| sb.append("00").append("50").append("04").append(hexString); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(logTag, "sensor no set: cooked: " + cooked); | |||
| Log.i(logTag, "sensor no set: cooked 2: " + Arrays.toString(cooked.getBytes())); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } | |||
| }; | |||
| private boolean from0to9(char c) { | |||
| return (c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9'); | |||
| } | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| if (rawData.getItemType() == RawData.TYPE_RECEIVE) { | |||
| Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData: " + rawData.getMessage()); | |||
| byte[] bytes = ByteUtils.hexStrToBytes(rawData.getMessage()); | |||
| Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData 2: " + Arrays.toString(bytes)); | |||
| if (bytes.length >= 8) { | |||
| if ((bytes[6] & 0xff) == 0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_51) { | |||
| Log.i(logTag, "ChangeSensorIdSettingsActivity, onSerialData, 0x51 feedback: " + rawData.getMessage()); | |||
| mPresenter.close(); | |||
| dismissDialog(settingsDialog); | |||
| dismissHandler.removeCallbacks(dismissRunnable); | |||
| runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_success, Toast.LENGTH_SHORT).show()); | |||
| finish(); | |||
| Intent intent = new Intent((ChangeSensorIdSettingsActivity.this), Main2Activity.class); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| startActivity(intent); | |||
| } else { | |||
| runOnUiThread(() -> Toast.makeText((ChangeSensorIdSettingsActivity.this), R.string.sensor_id_set_fail, Toast.LENGTH_SHORT).show()); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| } | |||
| } | |||
| @ -0,0 +1,258 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.annotation.SuppressLint; | |||
| import android.app.AlertDialog; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.os.Message; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.MotionEvent; | |||
| import android.view.View; | |||
| import android.view.inputmethod.InputMethodManager; | |||
| import android.widget.EditText; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.blankj.utilcode.util.ToastUtils; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import java.util.Arrays; | |||
| public class ConeSettingActivity extends BaseActivity implements SurfaceContract.ISerialView { | |||
| private static final String TAG = "HANDSET-JE002-EX"; | |||
| private Integer baudRate; | |||
| private String sensorId; | |||
| boolean eggNoRes = false, coneNoRes = false, coneUsedTimesRes = false, eggTypeRes = false; | |||
| private AlertDialog settingsDialog; | |||
| private AlertDialog getSettingsDialog; | |||
| private SurfacePresenter mPresenter = new SurfacePresenter((this)); | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_cone_setting); | |||
| Intent intent = getIntent(); | |||
| if (intent != null) { | |||
| baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); | |||
| sensorId = intent.getStringExtra(Constant.SENSOR_ID); | |||
| } | |||
| initView(); | |||
| } | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| } | |||
| @Override | |||
| protected void onPause() { | |||
| super.onPause(); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| mPresenter.close(); | |||
| super.onDestroy(); | |||
| } | |||
| @Override | |||
| public boolean onTouchEvent(MotionEvent event) { | |||
| InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); | |||
| if (im != null) { | |||
| View view = getCurrentFocus(); | |||
| if (view != null) { | |||
| im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); | |||
| } | |||
| } | |||
| return super.onTouchEvent(event); | |||
| } | |||
| private void initView() { | |||
| initTitle(); | |||
| } | |||
| public void onClickBtnSave(View view) { | |||
| String value = ((EditText) (findViewById(R.id.et_egg_num))).getText().toString(); | |||
| String value2 = ((EditText) (findViewById(R.id.et_cone_num))).getText().toString(); | |||
| String value3 = ((EditText) (findViewById(R.id.et_use_num))).getText().toString(); | |||
| String value4 = ((EditText) (findViewById(R.id.et_egg_type))).getText().toString(); | |||
| if(TextUtils.isEmpty(value) && TextUtils.isEmpty(value2) &&TextUtils.isEmpty(value3) && TextUtils.isEmpty(value4)) { | |||
| ToastUtils.showShort(getString(R.string.input_empty)); | |||
| } else { | |||
| showSettingDialog(); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_32, (3500)); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_36, (3700)); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_3A, (3800)); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_40, (3900)); | |||
| handler.sendEmptyMessageDelayed(Constant.READ_TIME_OUT, (10000)); | |||
| } | |||
| } | |||
| private void initTitle() { | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| tvTitle.setText(R.string.cone_info_title); | |||
| } | |||
| @SuppressLint("HandlerLeak") | |||
| private Handler handler = new Handler() { | |||
| @Override | |||
| public void handleMessage(Message msg) { | |||
| super.handleMessage(msg); | |||
| if (msg.what == Constant.Command.COMMAND_32) {//弹号设置 | |||
| String value = ((EditText) (findViewById(R.id.et_egg_num))).getText().toString(); | |||
| if (!TextUtils.isEmpty(value)) { | |||
| Log.i(TAG, "egg no set: sensorId: " + sensorId); | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| //String length = "0".concat(String.valueOf(value.length())); | |||
| String length = "0".concat(Integer.toHexString(value.length())); | |||
| String length2 = length.substring(length.length() - 2); | |||
| //Log.i(TAG, "egg no set: length2: " + length2); | |||
| sb.append("00").append("32").append(length2).append(ByteUtils.strToHexStr(value)); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(TAG, "egg no set: cooked: " + cooked); | |||
| Log.i(TAG, "egg no set: cooked 2: " + Arrays.toString(cooked.getBytes())); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } else if (msg.what == Constant.Command.COMMAND_36) {//筒号设置 | |||
| String value = ((EditText) (findViewById(R.id.et_cone_num))).getText().toString(); | |||
| if (!TextUtils.isEmpty(value)) { | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| //String length = "0".concat(String.valueOf(value.length())); | |||
| String length = "0".concat(Integer.toHexString(value.length())); | |||
| String length2 = length.substring(length.length() - 2); | |||
| sb.append("00").append("36").append(length2).append(ByteUtils.strToHexStr(value)); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(TAG, "cone no set: cooked: " + cooked); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } else if (msg.what == Constant.Command.COMMAND_3A) {//弹筒使用次数设置 | |||
| String value = ((EditText) (findViewById(R.id.et_use_num))).getText().toString(); | |||
| if (!TextUtils.isEmpty(value)) { | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| String length = "0".concat(String.valueOf(value.length())); | |||
| String length2 = length.substring(length.length() - 2); | |||
| sb.append("00").append("3A").append(length2).append(ByteUtils.strToHexStr(value)); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(TAG, "cone used times set: cooked: " + cooked); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } else if (msg.what == Constant.Command.COMMAND_40) { // 弹型 | |||
| String value = ((EditText) (findViewById(R.id.et_egg_type))).getText().toString(); | |||
| if (!TextUtils.isEmpty(value)) { | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| String length = "0".concat(Integer.toHexString(value.length())); | |||
| String length2 = length.substring(length.length() - 2); | |||
| sb.append("00").append("40").append(length2).append(ByteUtils.strToHexStr(value)); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(TAG, "egg type set: cooked: " + cooked); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } else if (msg.what == Constant.READ_TIME_OUT) { | |||
| if (eggNoRes || coneNoRes || coneUsedTimesRes || eggTypeRes) { | |||
| /*ToastUtils.showShort(R.string.setting_success);*/ | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(settingsDialog); | |||
| if (!(getSettingsDialog != null && getSettingsDialog.isShowing())) { | |||
| getSettingsDialog = ToastHelper.showSubmitDialog( | |||
| getString(R.string.set_cone_info_success), | |||
| R.mipmap.img_right, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.blue_button_bg), | |||
| getString(R.string.btn_ensure), | |||
| (ConeSettingActivity.this), | |||
| (View view) -> finish() | |||
| ); | |||
| } | |||
| }); | |||
| } else { | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(settingsDialog); | |||
| if (!(getSettingsDialog != null && getSettingsDialog.isShowing())) { | |||
| getSettingsDialog = ToastHelper.showSubmitDialog( | |||
| getString(R.string.set_cone_info_failed), | |||
| R.mipmap.img_cross, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.blue_button_bg), | |||
| getString(R.string.btn_ensure), | |||
| (ConeSettingActivity.this), | |||
| (View view) -> finish() | |||
| ); | |||
| } | |||
| }); | |||
| } | |||
| /*findViewById(R.id.btn_save).setEnabled(true); | |||
| findViewById(R.id.btn_save).setBackgroundResource(R.drawable.bg_start_btn_new); | |||
| ((Button) findViewById(R.id.btn_save)).setText(R.string.save_settings);*/ | |||
| } | |||
| } | |||
| }; | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| if (rawData.getItemType() == RawData.TYPE_RECEIVE) { | |||
| String message = rawData.getMessage(); | |||
| Log.i(TAG, "ConeSettingActivity, onSerialData: " + message); | |||
| byte[] bytes = ByteUtils.hexStrToBytes(message); | |||
| if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_33) { //egg no | |||
| eggNoRes = ((bytes[9] & 0xff) == 0xff); | |||
| } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_37) { //cone no | |||
| coneNoRes = (bytes[9] & 0xff) == 0xff; | |||
| } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_3B) { //cone used times | |||
| coneUsedTimesRes = (bytes[9] & 0xff) == 0xff; | |||
| } else if ((bytes[6] & 0xff) == 0x0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_41) { //egg type | |||
| eggTypeRes = (bytes[9] & 0xff) == 0xff; | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| } | |||
| private void showSettingDialog() { | |||
| runOnUiThread(() -> settingsDialog = ToastHelper.showTipDialog((ConeSettingActivity.this), R.mipmap.ic_setting, R.string.write_info_now_tips)); | |||
| } | |||
| } | |||
| @ -0,0 +1,238 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.app.AlertDialog; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.NonNull; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.constraint.ConstraintLayout; | |||
| import android.support.v7.widget.DefaultItemAnimator; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.view.ViewGroup; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.utils.DateUtils; | |||
| import com.handset.serialportsensor.utils.Slog; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import com.handset.serialportsensor.utils.ExcelMa; | |||
| import com.handset.serialportsensor.utils.PersistHelper; | |||
| import com.handset.serialportsensor.view.ExportProgressDialog; | |||
| import com.handset.serialportsensor.view.LinearLayoutManagerCus; | |||
| import java.io.File; | |||
| import java.util.ArrayList; | |||
| import java.util.List; | |||
| import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; | |||
| /** | |||
| * Created by zy on 2019/3/11. | |||
| */ | |||
| public class DataRecoverActivity extends BaseActivity { | |||
| private final String TAG = getClass().getSimpleName(); | |||
| private RecyclerView mRecyclerView; | |||
| private MyAdapter myAdapter; | |||
| boolean isRecovering = false; | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_recover_data); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText(R.string.data_recovery); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View v) -> onBackPressed()); | |||
| findViewById(R.id.btn_sure).setOnClickListener((View v) -> { | |||
| int index = myAdapter.getSelectIndex(); | |||
| if (index != -1) { | |||
| showRecoverConfirm(index); | |||
| } | |||
| }); | |||
| mRecyclerView = findViewById(R.id.recycle_view); | |||
| mRecyclerView.setLayoutManager(new LinearLayoutManagerCus((this))); | |||
| DefaultItemAnimator animator = new DefaultItemAnimator(); | |||
| animator.setRemoveDuration(1000); | |||
| mRecyclerView.setItemAnimator(animator); | |||
| getLocalFiles(); | |||
| } | |||
| ExcelMa excelMa = new ExcelMa(); | |||
| boolean recoverStatus = true; | |||
| private void recoverExcel(final int index) { | |||
| if (mFiles != null) { | |||
| mExportProgressDialog = null; | |||
| new Thread(() -> | |||
| excelMa.onReadClick(mFiles.get(index), new PersistHelper.ExportCallback() { | |||
| @Override | |||
| public void exportProgress(int counts, int remain) { | |||
| updateView(counts, remain); | |||
| recoverStatus = true; | |||
| } | |||
| @Override | |||
| public void finish(int counts, int remain) { | |||
| if (remain != 0) { | |||
| showCancelTip(); | |||
| recoverStatus = true; | |||
| } else { | |||
| recoverStatus = false; | |||
| } | |||
| } | |||
| }) | |||
| ).start(); | |||
| } | |||
| } | |||
| private void showCancelTip() { | |||
| runOnUiThread(() -> { | |||
| AlertDialog alertDialog = ToastHelper.showTipDialogNoShow((DataRecoverActivity.this), R.mipmap.chuchang_gray, R.string.cancel); | |||
| showDialog(alertDialog); | |||
| disMissDialogDelay(alertDialog, (3000)); | |||
| }); | |||
| } | |||
| private void showRecoverConfirm(final int index) { | |||
| runOnUiThread(() -> { | |||
| dismissDialog((null)); | |||
| showExportProgress((0), (0)); | |||
| AlertDialog a = ToastHelper.showChooseDialogNoShow(getString(R.string.data_recovery_confirm), R.mipmap.ic_exclamation_mark, | |||
| getString(R.string.recover_data_alarm), getResources().getColor(R.color.button), | |||
| getString(R.string.confirm), getString(R.string.cancel), (DataRecoverActivity.this), new ToastHelper.OnDialogClickListener() { | |||
| @Override | |||
| public void onOKClickListener(View view) { | |||
| recoverExcel(index); | |||
| } | |||
| @Override | |||
| public void onCancelClickListener(View view) { | |||
| } | |||
| }); | |||
| showDialog(a); | |||
| }); | |||
| } | |||
| public void updateView(int counts, int remain) { | |||
| showExportProgress(counts, remain); | |||
| } | |||
| ExportProgressDialog mExportProgressDialog; | |||
| private void showExportProgress(final int count, final int remain) { | |||
| if (mExportProgressDialog == null) { | |||
| runOnUiThread(() -> { | |||
| mExportProgressDialog = new ExportProgressDialog(); | |||
| mExportProgressDialog.showExportDialogNoShow((DataRecoverActivity.this), | |||
| (View view) -> { | |||
| if (recoverStatus) { | |||
| excelMa.stopExport(); | |||
| } else { | |||
| DataRecoverActivity.this.finish(); | |||
| } | |||
| }, count, remain, getString(R.string.data_recovering), getString(R.string.recovery_data)); | |||
| showDialog(mExportProgressDialog.mAlertDialog); | |||
| }); | |||
| } else { | |||
| mExportProgressDialog.update((this), count, remain); | |||
| } | |||
| } | |||
| @Override | |||
| public void onBackPressed() { | |||
| if (!isRecovering) { | |||
| DataRecoverActivity.this.finish(); | |||
| } | |||
| } | |||
| List<File> mFiles; | |||
| private void getLocalFiles() { | |||
| mFiles = Slog.getFiles(ExcelMa.getSavePath(), new ArrayList<>()); | |||
| initData(mFiles); | |||
| } | |||
| void initData(List<File> list) { | |||
| //设置适配器 | |||
| myAdapter = new MyAdapter(list); | |||
| myAdapter.setOnItemClickListener((View view, int position) -> { | |||
| }); | |||
| mRecyclerView.setAdapter(myAdapter); | |||
| } | |||
| static class ViewHolder extends RecyclerView.ViewHolder { | |||
| TextView tvName; | |||
| TextView tv_file_size; | |||
| TextView tv_end_time; | |||
| ImageView ivSelect; | |||
| ConstraintLayout cl_content; | |||
| ViewHolder(@NonNull View itemView) { | |||
| super(itemView); | |||
| tvName = itemView.findViewById(R.id.tv_name); | |||
| tv_file_size = itemView.findViewById(R.id.tv_file_size); | |||
| tv_end_time = itemView.findViewById(R.id.tv_end_time); | |||
| ivSelect = itemView.findViewById(R.id.iv_select); | |||
| cl_content = itemView.findViewById(R.id.cl_content); | |||
| } | |||
| } | |||
| static class MyAdapter extends RecyclerView.Adapter<ViewHolder> { | |||
| List<File> mDataList; | |||
| private OnItemClickListener mOnItemClickListener; | |||
| int indexSelect = -1; | |||
| MyAdapter(List<File> mList) { | |||
| this.mDataList = mList; | |||
| } | |||
| int getSelectIndex() { | |||
| return indexSelect; | |||
| } | |||
| @NonNull | |||
| @Override | |||
| public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { | |||
| return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.revocer_data_item, null, false)); | |||
| } | |||
| @Override | |||
| public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { | |||
| File f = mDataList.get(viewHolder.getAdapterPosition()); | |||
| String text = f.length() / (1024) + "kb"; | |||
| viewHolder.tv_file_size.setText(text); | |||
| viewHolder.tvName.setText(f.getName()); | |||
| viewHolder.tv_end_time.setText(DateUtils.formatMilliesTimestamp(f.lastModified(), YYYY_MM_DD_HH_MM_SS)); | |||
| if (indexSelect == viewHolder.getAdapterPosition()) { | |||
| viewHolder.ivSelect.setImageResource(R.mipmap.ic_selected); | |||
| } else { | |||
| viewHolder.ivSelect.setImageResource(R.mipmap.ic_default); | |||
| } | |||
| viewHolder.cl_content.setOnClickListener((View v) -> { | |||
| indexSelect = viewHolder.getAdapterPosition(); | |||
| notifyDataSetChanged(); | |||
| }); | |||
| } | |||
| @Override | |||
| public int getItemCount() { | |||
| return mDataList.size(); | |||
| } | |||
| void setOnItemClickListener(OnItemClickListener onItemClickListener) { | |||
| this.mOnItemClickListener = onItemClickListener; | |||
| } | |||
| } | |||
| public interface OnItemClickListener { | |||
| void onItemClick(View view, int position); | |||
| } | |||
| } | |||
| @ -0,0 +1,284 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.NonNull; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.support.v7.widget.DefaultItemAnimator; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.view.ViewGroup; | |||
| import android.widget.Button; | |||
| import android.widget.ImageView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.Sensor; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.utils.Utils; | |||
| import com.handset.serialportsensor.view.LinearLayoutManagerCus; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.util.List; | |||
| public class HistoryActivity extends AppCompatActivity { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private boolean delStatus = false; | |||
| private RecyclerView mRecyclerView; | |||
| private MyAdapter myAdapter; | |||
| private LinearLayout llDeleteContent; | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_history); | |||
| mRecyclerView = findViewById(R.id.recycle_view); | |||
| mRecyclerView.setLayoutManager(new LinearLayoutManagerCus(this)); | |||
| DefaultItemAnimator animator = new DefaultItemAnimator(); | |||
| animator.setRemoveDuration(1000); | |||
| mRecyclerView.setItemAnimator(animator); | |||
| initData(); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText(R.string.test_history); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View v) -> HistoryActivity.this.finish()); | |||
| Button btnSelAll = findViewById(R.id.btn_select_all); | |||
| btnSelAll.setOnClickListener((View v) -> myAdapter.selAll()); | |||
| Button btnDelete = findViewById(R.id.btn_delete); | |||
| btnDelete.setOnClickListener((View v) -> { | |||
| delStatus = false; | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| myAdapter.delSelected(); | |||
| }); | |||
| Button btnCancel = findViewById(R.id.btn_cancel); | |||
| btnCancel.setOnClickListener((View v) -> { | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| myAdapter.setDeleteStatus(false); | |||
| delStatus = false; | |||
| myAdapter.cancelSelected(); | |||
| }); | |||
| llDeleteContent = findViewById(R.id.ll_delete_content); | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| //initSensor(); | |||
| } | |||
| void initData() { | |||
| final List<Sensor> sensors = KJDB.getDefaultInstance().findAll(Sensor.class); | |||
| for (Sensor sensor : sensors) { | |||
| Log.i(logTag, ("list every sensorId: " + sensor.sensor_id + ", id: " + sensor.id)); | |||
| } | |||
| if (myAdapter == null) { | |||
| myAdapter = new MyAdapter(sensors, (View v) -> { | |||
| if (delStatus) { | |||
| return true; | |||
| } else { | |||
| delStatus = true; | |||
| myAdapter.setDeleteStatus(true); | |||
| llDeleteContent.setVisibility(View.VISIBLE); | |||
| } | |||
| return false; | |||
| }); | |||
| } | |||
| myAdapter.setOnItemClickListener((View view, int position) -> { | |||
| Intent intent = new Intent((HistoryActivity.this), HistoryDetailActivity.class); | |||
| Log.e(logTag, "History Activity id: " + sensors.get(position).id + ", sensorId: " + sensors.get(position).sensor_id); | |||
| intent.putExtra(Constant.SENSOR_ID, sensors.get(position).id); | |||
| startActivity(intent); | |||
| }); | |||
| mRecyclerView.setAdapter(myAdapter); | |||
| } | |||
| static class ViewHolder extends RecyclerView.ViewHolder { | |||
| private TextView tvEggNum; | |||
| private TextView tvEggType; | |||
| private TextView tvConeNo; | |||
| private TextView tvSensorId; | |||
| private TextView tvConeUsedTimes; | |||
| private TextView tvPro; | |||
| private LinearLayout llItem; | |||
| private ImageView ivSelectStatus; | |||
| private ViewHolder(@NonNull View itemView) { | |||
| super(itemView); | |||
| tvEggNum = itemView.findViewById(R.id.tv_his_egg_num); | |||
| tvEggType = itemView.findViewById(R.id.tv_his_egg_type); | |||
| tvConeNo = itemView.findViewById(R.id.tv_his_cone_no); | |||
| tvSensorId = itemView.findViewById(R.id.tv_his_sensor_id); | |||
| tvPro = itemView.findViewById(R.id.tv_his_pro); | |||
| tvConeUsedTimes = itemView.findViewById(R.id.tv_his_cone_used_times); | |||
| llItem = itemView.findViewById(R.id.ll_his_item); | |||
| ivSelectStatus = itemView.findViewById(R.id.iv_select_status); | |||
| } | |||
| } | |||
| public static class MyAdapter extends RecyclerView.Adapter<ViewHolder> { | |||
| private boolean delStatus = false; | |||
| private List<Sensor> mDataList; | |||
| private OnItemClickListener mOnItemClickListener; | |||
| private View.OnLongClickListener mOnLongClickListener; | |||
| MyAdapter(List<Sensor> mList, View.OnLongClickListener longClickListener) { | |||
| this.mDataList = mList; | |||
| this.mOnLongClickListener = longClickListener; | |||
| } | |||
| @NonNull | |||
| @Override | |||
| public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { | |||
| return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.history_item, viewGroup, (false))); | |||
| } | |||
| @Override | |||
| public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int i) { | |||
| final Sensor sensor = mDataList.get(i); | |||
| viewHolder.tvEggNum.setText(TextUtils.isEmpty(sensor.egg_id) ? " " : " ".concat(sensor.egg_id)); | |||
| viewHolder.tvEggType.setText(TextUtils.isEmpty(sensor.egg_type) ? " " : " ".concat(sensor.egg_type)); | |||
| viewHolder.tvConeNo.setText(TextUtils.isEmpty(sensor.tupe_id) ? " " : " ".concat(sensor.tupe_id)); | |||
| viewHolder.tvSensorId.setText(Utils.getSensorNoShow(String.valueOf(sensor.sensor_id))); | |||
| viewHolder.tvPro.setText(String.valueOf(sensor.sensor_id).length() < 5 ? "" : String.valueOf(String.valueOf(sensor.sensor_id).charAt(4))); | |||
| viewHolder.llItem.setOnLongClickListener((View v) -> { | |||
| if (mOnLongClickListener != null) { | |||
| mOnLongClickListener.onLongClick(v); | |||
| } | |||
| return false; | |||
| }); | |||
| viewHolder.ivSelectStatus.setVisibility(this.delStatus ? View.VISIBLE : View.GONE); | |||
| if (delStatus) { | |||
| viewHolder.ivSelectStatus.setImageResource(sensor.tagBackup == 1 ? R.mipmap.ic_selected : R.mipmap.ic_default); | |||
| viewHolder.llItem.setOnClickListener((View v) -> { | |||
| sensor.tagBackup = sensor.tagBackup == 0 ? 1 : 0; | |||
| notifyDataSetChanged(); | |||
| }); | |||
| } else { | |||
| viewHolder.llItem.setOnClickListener((View v) -> { | |||
| if (mOnItemClickListener != null) { | |||
| mOnItemClickListener.onItemClick(v, viewHolder.getAdapterPosition()); | |||
| } | |||
| }); | |||
| } | |||
| viewHolder.tvConeUsedTimes.setText(" ".concat(TextUtils.isEmpty(sensor.tv_tupe_use_times) ? "0" : sensor.tv_tupe_use_times)); | |||
| } | |||
| @Override | |||
| public int getItemCount() { | |||
| return mDataList.size(); | |||
| } | |||
| private void setOnItemClickListener(OnItemClickListener onItemClickListener) { | |||
| this.mOnItemClickListener = onItemClickListener; | |||
| } | |||
| private void setDeleteStatus(boolean delStatus) { | |||
| this.delStatus = delStatus; | |||
| notifyDataSetChanged(); | |||
| } | |||
| void selAll() { | |||
| for (Sensor sensor : mDataList) { | |||
| sensor.tagBackup = 1; | |||
| } | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void delSelected() { | |||
| for (int i = mDataList.size() - 1; i >= 0; i--) { | |||
| Sensor t = mDataList.get(i); | |||
| if (t.tagBackup == 1) { | |||
| KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "sensor_id = " + t.sensor_id); | |||
| KJDB.getDefaultInstance().deleteById(Sensor.class, t.id); | |||
| mDataList.remove(i); | |||
| } | |||
| } | |||
| delStatus = false; | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void cancelSelected() { | |||
| for (Sensor sensor : mDataList) { | |||
| sensor.tagBackup = 0; | |||
| } | |||
| } | |||
| } | |||
| public interface OnItemClickListener { | |||
| void onItemClick(View view, int position); | |||
| } | |||
| @SuppressWarnings(value = "all") | |||
| void initSensor() { | |||
| Sensor sensor = new Sensor(); | |||
| sensor.id = 1; | |||
| sensor.egg_id = "EGG1"; | |||
| sensor.sensor_id = 19011111; | |||
| sensor.egg_type = "EGGA"; | |||
| sensor.tupe_id = "TUPEA"; | |||
| KJDB.getDefaultInstance().save(sensor); | |||
| sensor.id = 2; | |||
| sensor.egg_id = "EGG2"; | |||
| sensor.sensor_id = 19011112; | |||
| sensor.egg_type = "EGGB"; | |||
| sensor.tupe_id = "TUPEB"; | |||
| KJDB.getDefaultInstance().save(sensor); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| int i = 1; | |||
| for (; i < 25; i++) { | |||
| testRecordsTotal.id = i; | |||
| testRecordsTotal.end_time = System.currentTimeMillis(); | |||
| testRecordsTotal.Hum = 80; | |||
| testRecordsTotal.sensor_id = 1; | |||
| testRecordsTotal.pressure_yacha = 100; | |||
| testRecordsTotal.pressurein = 90; | |||
| testRecordsTotal.pressureout = 120; | |||
| testRecordsTotal.temp = 50; | |||
| testRecordsTotal.Hum20 = 90; | |||
| testRecordsTotal.pressurein20 = 20; | |||
| testRecordsTotal.tupe_use_times = "10"; | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| } | |||
| i = 1; | |||
| for (; i < 25; i++) { | |||
| testRecordsTotal.id = i; | |||
| testRecordsTotal.Hum = 80; | |||
| testRecordsTotal.sensor_id = 1; | |||
| testRecordsTotal.pressure_yacha = 100; | |||
| testRecordsTotal.pressurein = 90; | |||
| testRecordsTotal.pressureout = 120; | |||
| testRecordsTotal.temp = 50; | |||
| testRecordsTotal.Hum20 = 90; | |||
| testRecordsTotal.pressurein20 = 20; | |||
| testRecordsTotal.tupe_use_times = "10"; | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| } | |||
| i = 1; | |||
| for (; i < 25; i++) { | |||
| testRecordsTotal.id = i; | |||
| testRecordsTotal.end_time = System.currentTimeMillis() - 2 * 24 * 60 * 60 * 1000; | |||
| testRecordsTotal.Hum = 80; | |||
| testRecordsTotal.sensor_id = 1; | |||
| testRecordsTotal.pressure_yacha = 100; | |||
| testRecordsTotal.pressurein = 90; | |||
| testRecordsTotal.pressureout = 120; | |||
| testRecordsTotal.temp = 50; | |||
| testRecordsTotal.Hum20 = 90; | |||
| testRecordsTotal.pressurein20 = 20; | |||
| testRecordsTotal.tupe_use_times = "10"; | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,482 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.app.DatePickerDialog; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.graphics.Color; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.NonNull; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.view.ViewGroup; | |||
| import android.widget.BaseAdapter; | |||
| import android.widget.Button; | |||
| import android.widget.DatePicker; | |||
| import android.widget.ImageView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.google.gson.Gson; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.Sensor; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import com.handset.serialportsensor.bean.ThresholdBean; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.utils.DateUtils; | |||
| import com.handset.serialportsensor.utils.SPUtils; | |||
| import com.handset.serialportsensor.utils.SpUtil; | |||
| import com.handset.serialportsensor.utils.Utils; | |||
| import com.handset.serialportsensor.view.AutoLoadMoreListView; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.text.DecimalFormat; | |||
| import java.util.ArrayList; | |||
| import java.util.Calendar; | |||
| import java.util.List; | |||
| import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD; | |||
| import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; | |||
| /** | |||
| * Created by zy on 2019/2/24. | |||
| */ | |||
| public class HistoryDetailActivity extends AppCompatActivity { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private final static int ZERO = 0; | |||
| private final static boolean FALSE = false; | |||
| private final static boolean TRUE = true; | |||
| private final static int REQUEST_START_TIME = 100; | |||
| private final static int REQUEST_END_TIME = 101; | |||
| private final static int PAGE_SIZE = 8; //每页显示的数据条数 | |||
| private boolean delStatus = false; | |||
| private TextView tvStartTime; | |||
| private TextView tvEndTime; | |||
| private Sensor mSensor; | |||
| private LinearLayout llDeleteContent; | |||
| private AutoLoadMoreListView mRecyclerView; | |||
| private MyAdapter myAdapter; | |||
| private int currentPagedIndex = 0;//当前页码 | |||
| private TextView etCurPage; | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_history_detail); | |||
| int id = getIntent().getIntExtra(Constant.SENSOR_ID, ZERO); | |||
| mSensor = KJDB.getDefaultInstance().findById(id, Sensor.class); | |||
| if (mSensor == null) { | |||
| finish(); | |||
| } | |||
| initView(); | |||
| initData(); | |||
| } | |||
| void initView() { | |||
| tvStartTime = findViewById(R.id.tv_his_detail_start_time); | |||
| tvStartTime.setOnClickListener((View v) -> pickData(REQUEST_START_TIME)); | |||
| tvStartTime.setEnabled(true); | |||
| tvEndTime = findViewById(R.id.tv_his_detail_end_time); | |||
| tvEndTime.setOnClickListener((View v) -> pickData(REQUEST_END_TIME)); | |||
| etCurPage = findViewById(R.id.et_curr_page); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText(Utils.getSensorNoShow(String.valueOf(mSensor.sensor_id))); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View v) -> HistoryDetailActivity.this.finish()); | |||
| mRecyclerView = findViewById(R.id.recycle_view); | |||
| mRecyclerView.setShowLoadMore(true); | |||
| mRecyclerView.setLoadMoreListener((AutoLoadMoreListView listView) -> { | |||
| Log.d(logTag, "onLoadMoreBegin [listView]:"); | |||
| if (!loadAll) { | |||
| search((true)); | |||
| } | |||
| }); | |||
| Button btnSelAll = findViewById(R.id.btn_select_all); | |||
| btnSelAll.setOnClickListener((View v) -> myAdapter.selAll()); | |||
| Button btnDelete = findViewById(R.id.btn_delete); | |||
| btnDelete.setOnClickListener((View v) -> { | |||
| delStatus = false; | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| myAdapter.delSelected(); | |||
| }); | |||
| Button btnCancel = findViewById(R.id.btn_cancel); | |||
| btnCancel.setOnClickListener((View v) -> { | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| myAdapter.setDeleteStatus(false); | |||
| delStatus = false; | |||
| }); | |||
| llDeleteContent = findViewById(R.id.ll_delete_content); | |||
| llDeleteContent.setVisibility(View.GONE); | |||
| } | |||
| void initData() { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.set(calendar.get(Calendar.YEAR), | |||
| calendar.get(Calendar.MONTH), | |||
| calendar.get(Calendar.DAY_OF_MONTH), ZERO, ZERO, ZERO); | |||
| long t = calendar.getTimeInMillis(); | |||
| start_time = t - 31536000000L; | |||
| start_time = SPUtils.getInstance(this).get("search_history_start_time", start_time); | |||
| calendar.set(calendar.get(Calendar.YEAR), | |||
| calendar.get(Calendar.MONTH), | |||
| calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59); | |||
| end_time = calendar.getTimeInMillis(); | |||
| Log.i(logTag, ("initData, start_time: " + start_time + ", end_time: " + end_time)); | |||
| end_time = SPUtils.getInstance(this).get("search_history_end_time", end_time); | |||
| loadAll = false; | |||
| search((false)); | |||
| } | |||
| public static class ViewHolder extends RecyclerView.ViewHolder { | |||
| private TextView tvPreIn20; | |||
| private TextView tvHumidity20; | |||
| private TextView tvTemperature; | |||
| private TextView tvHumidity; | |||
| private TextView tvPreIn; | |||
| private TextView tvPreOut; | |||
| private TextView tvProId; | |||
| private TextView tvBotLv; | |||
| LinearLayout llTemperature; | |||
| LinearLayout llHumidity; | |||
| LinearLayout llPreIn; | |||
| LinearLayout llPreOut; | |||
| TextView tvPressureDiff; | |||
| TextView tvStartTime; | |||
| TextView tvEndTime; | |||
| TextView tvItemIndex; | |||
| LinearLayout llItem; | |||
| ImageView ivSelectStatus; | |||
| private ViewHolder(@NonNull View itemView) { | |||
| super(itemView); | |||
| tvPreIn20 = itemView.findViewById(R.id.tv_in_pre_20); | |||
| tvHumidity20 = itemView.findViewById(R.id.tv_shidu20); | |||
| tvTemperature = itemView.findViewById(R.id.tv_temp); | |||
| tvHumidity = itemView.findViewById(R.id.tv_shidu); | |||
| tvPreIn = itemView.findViewById(R.id.tv_pre_in); | |||
| tvPreOut = itemView.findViewById(R.id.tv_pre_out); | |||
| llTemperature = itemView.findViewById(R.id.ll_temp); | |||
| llHumidity = itemView.findViewById(R.id.ll_shidu); | |||
| llPreIn = itemView.findViewById(R.id.ll_pre_in); | |||
| llPreOut = itemView.findViewById(R.id.ll_pre_out); | |||
| tvPressureDiff = itemView.findViewById(R.id.tv_yacha); | |||
| tvStartTime = itemView.findViewById(R.id.tv_start_time); | |||
| tvEndTime = itemView.findViewById(R.id.tv_end_time); | |||
| tvItemIndex = itemView.findViewById(R.id.tv_item_index); | |||
| tvProId = itemView.findViewById(R.id.tv_pro_id); | |||
| tvBotLv = itemView.findViewById(R.id.tv_botelv); | |||
| llItem = itemView.findViewById(R.id.ll_item); | |||
| ivSelectStatus = itemView.findViewById(R.id.iv_select_status); | |||
| } | |||
| } | |||
| public static class MyAdapter extends BaseAdapter { | |||
| private Context mContext; | |||
| private ThresholdBean bean; | |||
| private boolean delStatus = false; | |||
| private List<TestRecordsTotal> mDataList; | |||
| private View.OnLongClickListener mOnLongClickListener; | |||
| private void setDataList(List<TestRecordsTotal> mList) { | |||
| if (mDataList == null) { | |||
| mDataList = new ArrayList<>(); | |||
| } | |||
| mDataList.clear(); | |||
| mDataList.addAll(mList); | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void delSelected() { | |||
| for (int i = mDataList.size() - 1; i >= 0; i--) { | |||
| TestRecordsTotal t = mDataList.get(i); | |||
| if (t.tagBackup == 1) { | |||
| KJDB.getDefaultInstance().deleteById(TestRecordsTotal.class, t.id); | |||
| mDataList.remove(i); | |||
| } | |||
| } | |||
| this.delStatus = false; | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void selAll() { | |||
| for (TestRecordsTotal testRecordsTotal : mDataList) { | |||
| testRecordsTotal.tagBackup = 1; | |||
| } | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void setDeleteStatus(boolean status) { | |||
| this.delStatus = status; | |||
| notifyDataSetChanged(); | |||
| } | |||
| private void appendDataList(List<TestRecordsTotal> mList) { | |||
| if (mDataList == null) { | |||
| mDataList = new ArrayList<>(); | |||
| } | |||
| mDataList.addAll(mList); | |||
| notifyDataSetChanged(); | |||
| } | |||
| private MyAdapter(Context context, List<TestRecordsTotal> mList, View.OnLongClickListener longClickListener) { | |||
| this.mDataList = new ArrayList<>(); | |||
| mDataList.addAll(mList); | |||
| mContext = context; | |||
| bean = new ThresholdBean(); | |||
| bean.setTemperatureFloor("-40"); | |||
| bean.setTemperatureCeiling("65"); | |||
| bean.setHumidityFloor("0"); | |||
| bean.setHumidityCeiling("100"); | |||
| bean.setInnerPressureFloor("80"); | |||
| bean.setInnerPressureCeiling("150"); | |||
| bean.setOuterPressureFloor("80"); | |||
| bean.setOuterPressureCeiling("150"); | |||
| bean.setDiffPressureFloor("-20"); | |||
| bean.setDiffPressureCeiling("30"); | |||
| String bean2 = (String) SpUtil.get(context, Constant.THRESHOLD_KEY, ""); | |||
| if (!TextUtils.isEmpty(bean2)) { | |||
| bean = new Gson().fromJson(bean2, ThresholdBean.class); | |||
| } | |||
| this.mOnLongClickListener = longClickListener; | |||
| } | |||
| private void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { | |||
| final TestRecordsTotal sensor = mDataList.get(i); | |||
| DecimalFormat df = new DecimalFormat("0.00"); | |||
| viewHolder.tvHumidity20.setText(df.format(sensor.Hum20)); | |||
| viewHolder.tvPreIn20.setText(df.format(sensor.pressurein20)); | |||
| viewHolder.tvTemperature.setText(df.format(sensor.temp)); | |||
| viewHolder.tvHumidity.setText(df.format(sensor.Hum)); | |||
| viewHolder.tvPreIn.setText(df.format(sensor.pressurein)); | |||
| viewHolder.tvPreOut.setText(df.format(sensor.pressureout)); | |||
| viewHolder.tvPressureDiff.setText(df.format(sensor.pressure_yacha)); | |||
| String ids = String.valueOf(sensor.sensor_id); | |||
| viewHolder.tvProId.setText(ids.length() < 5 ? "" : ids.substring(4, 5)); | |||
| viewHolder.tvBotLv.setText(sensor.botelv); | |||
| viewHolder.tvStartTime.setVisibility(View.GONE); | |||
| viewHolder.tvEndTime.setText(DateUtils.formatMilliesTimestamp(sensor.end_time, YYYY_MM_DD_HH_MM_SS)); | |||
| if (bean != null) { | |||
| viewHolder.tvTemperature.setTextColor(Color.parseColor(sensor.temp > Float.parseFloat(bean.getTemperatureFloor()) && sensor.temp < Float.parseFloat(bean.getTemperatureCeiling()) ? "#333333" : "#F02323")); | |||
| viewHolder.tvHumidity.setTextColor(Color.parseColor(sensor.Hum > Float.parseFloat(bean.getHumidityFloor()) && sensor.Hum < Float.parseFloat(bean.getHumidityCeiling()) ? "#333333" : "#F02323")); | |||
| viewHolder.tvPreIn.setTextColor(Color.parseColor(sensor.pressurein > Float.parseFloat(bean.getInnerPressureFloor()) && sensor.pressurein < Float.parseFloat(bean.getInnerPressureCeiling()) ? "#333333" : "#F02323")); | |||
| viewHolder.tvPreOut.setTextColor(Color.parseColor(sensor.pressureout > Float.parseFloat(bean.getOuterPressureFloor()) && sensor.pressureout < Float.parseFloat(bean.getOuterPressureCeiling()) ? "#333333" : "#F02323")); | |||
| viewHolder.tvPressureDiff.setTextColor(Color.parseColor(sensor.pressure_yacha > Float.parseFloat(bean.getDiffPressureFloor()) && sensor.pressure_yacha < Float.parseFloat(bean.getDiffPressureCeiling()) ? "#333333" : "#F02323")); | |||
| } | |||
| viewHolder.llItem.setOnLongClickListener((View v) -> { | |||
| if (mOnLongClickListener != null) { | |||
| mOnLongClickListener.onLongClick(v); | |||
| } | |||
| return false; | |||
| }); | |||
| viewHolder.ivSelectStatus.setVisibility(this.delStatus ? View.VISIBLE : View.GONE); | |||
| if (this.delStatus) { | |||
| viewHolder.ivSelectStatus.setImageResource(sensor.tagBackup == 1 ? R.mipmap.ic_selected : R.mipmap.ic_default); | |||
| viewHolder.llItem.setOnClickListener((View v) -> { | |||
| sensor.tagBackup = sensor.tagBackup == 0 ? 1 : 0; | |||
| notifyDataSetChanged(); | |||
| }); | |||
| } else { | |||
| viewHolder.llItem.setOnClickListener(null); | |||
| } | |||
| } | |||
| private int getItemCount() { | |||
| return mDataList == null ? 0 : mDataList.size(); | |||
| } | |||
| @Override | |||
| public int getCount() { | |||
| return getItemCount(); | |||
| } | |||
| @Override | |||
| public Object getItem(int position) { | |||
| return mDataList.get(position); | |||
| } | |||
| @Override | |||
| public long getItemId(int position) { | |||
| return 0; | |||
| } | |||
| @Override | |||
| public View getView(int position, View convertView, ViewGroup parent) { | |||
| ViewHolder viewHolder; | |||
| if (convertView == null) { | |||
| convertView = LayoutInflater.from(mContext).inflate(R.layout.activity_history_detail_item, parent, false); | |||
| viewHolder = new ViewHolder(convertView); | |||
| convertView.setTag(viewHolder); | |||
| } else { | |||
| viewHolder = (ViewHolder) convertView.getTag(); | |||
| } | |||
| onBindViewHolder(viewHolder, position); | |||
| return convertView; | |||
| } | |||
| } | |||
| private void pickData(final int requestCode) { | |||
| Calendar calendar2 = Calendar.getInstance(); | |||
| Log.e(logTag, ("startTime: " + start_time + ", end_time: " + end_time)); | |||
| calendar2.setTimeInMillis(requestCode == REQUEST_START_TIME ? start_time : end_time); | |||
| new DatePickerDialog(this, (DatePicker view, int year, int month, int dayOfMonth) -> { | |||
| Calendar calendar = Calendar.getInstance(); | |||
| long t = calendar.getTimeInMillis(); | |||
| if (requestCode == REQUEST_END_TIME) { | |||
| calendar.set(year, month, dayOfMonth, 23, 59, 59); | |||
| if (t == 0) { | |||
| Toast.makeText(HistoryDetailActivity.this, "请选择结束时间", Toast.LENGTH_SHORT).show(); | |||
| } else { | |||
| t = calendar.getTimeInMillis(); | |||
| end_time = t; | |||
| SPUtils.getInstance(HistoryDetailActivity.this).put("search_history_end_time", end_time); | |||
| } | |||
| loadAll = false; | |||
| search(false); | |||
| } else if (requestCode == REQUEST_START_TIME) { | |||
| calendar.set(year, month, dayOfMonth, 0, 0, 0); | |||
| if (t == 0) { | |||
| Toast.makeText(HistoryDetailActivity.this, "请选择开始时间", Toast.LENGTH_SHORT).show(); | |||
| } else { | |||
| t = calendar.getTimeInMillis(); | |||
| start_time = t; | |||
| SPUtils.getInstance(HistoryDetailActivity.this).put("search_history_start_time", start_time); | |||
| } | |||
| loadAll = false; | |||
| search(false); | |||
| } | |||
| }, calendar2.get(Calendar.YEAR), calendar2.get(Calendar.MONTH), calendar2.get(Calendar.DAY_OF_MONTH)).show(); | |||
| } | |||
| long start_time = 0; | |||
| long end_time = 0; | |||
| @Override | |||
| protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { | |||
| super.onActivityResult(requestCode, resultCode, data); | |||
| if (resultCode == RESULT_OK) { | |||
| Log.d(logTag, ("result ok")); | |||
| } | |||
| } | |||
| public long findStartId(long start_time, long end_time) {//查找perPageItems条 | |||
| if (start_time > end_time) return 0; | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(end_time); | |||
| long startDatT = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; | |||
| List<TestRecordsTotal> t = KJDB.getDefaultInstance().findAllByWhere(TestRecordsTotal.class, "day_t = " + startDatT + " And sensor_id = " + mSensor.sensor_id, "end_time desc"); | |||
| long curId; | |||
| if (t != null && t.size() > 0) { | |||
| curId = t.get(0).id; | |||
| for (int i = 1; i < t.size(); i++) { | |||
| long tempId = t.get(i).id; | |||
| if (curId < tempId) { | |||
| curId = tempId; | |||
| } | |||
| } | |||
| return curId; | |||
| } | |||
| return findStartId(start_time, end_time - 24 * 3600000); | |||
| } | |||
| public TestRecordsTotal findNextItem(long start_time, long end_time) { | |||
| if (startId <= 0) { | |||
| return null; | |||
| } | |||
| TestRecordsTotal t = KJDB.getDefaultInstance().findById(startId, TestRecordsTotal.class); | |||
| startId--; | |||
| if (t != null) { | |||
| if (t.end_time >= start_time && t.end_time <= end_time) { | |||
| if (t.sensor_id != mSensor.sensor_id) { | |||
| return findNextItem(start_time, end_time); | |||
| } | |||
| return t; | |||
| } | |||
| } else { | |||
| return findNextItem(start_time, end_time); | |||
| } | |||
| return null; | |||
| } | |||
| long startId = 0; | |||
| boolean loadAll = false; | |||
| private void search(boolean append) { | |||
| if (!append) { | |||
| startId = 0; | |||
| } | |||
| if (start_time >= end_time) { | |||
| return; | |||
| } | |||
| tvStartTime.setText(DateUtils.formatMilliesTimestamp(start_time, YYYY_MM_DD)); | |||
| tvEndTime.setText(DateUtils.formatMilliesTimestamp(end_time, YYYY_MM_DD)); | |||
| if (startId == 0) { | |||
| startId = findStartId(start_time, end_time); | |||
| } | |||
| List<TestRecordsTotal> testRecordsTotals = new ArrayList<>(); | |||
| boolean tagLoadMore = true; | |||
| if (startId != 0) { | |||
| for (int i = 0; i < PAGE_SIZE; i++) { | |||
| TestRecordsTotal t = findNextItem(start_time, end_time); | |||
| if (t != null) { | |||
| testRecordsTotals.add(t); | |||
| } | |||
| } | |||
| } | |||
| if (testRecordsTotals.size() < PAGE_SIZE) { | |||
| tagLoadMore = false; | |||
| } | |||
| String curPageIndex = String.valueOf(currentPagedIndex + 1); | |||
| etCurPage.setText(curPageIndex); | |||
| mRecyclerView.setShowLoadMore(tagLoadMore); | |||
| updateListView(testRecordsTotals, append); | |||
| mRecyclerView.loadMoreComplete(); | |||
| } | |||
| void updateListView(List<TestRecordsTotal> list, boolean append) { | |||
| if (myAdapter == null) { | |||
| myAdapter = new MyAdapter((this), list, (View v) -> { | |||
| if (delStatus) { | |||
| return true; | |||
| } | |||
| delStatus = true; | |||
| myAdapter.setDeleteStatus(true); | |||
| llDeleteContent.setVisibility(View.VISIBLE); | |||
| return false; | |||
| }); | |||
| mRecyclerView.setAdapter(myAdapter); | |||
| } else { | |||
| if (append) { | |||
| myAdapter.appendDataList(list); | |||
| } else { | |||
| myAdapter.setDataList(list); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,253 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.app.AlertDialog; | |||
| import android.content.Context; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.MotionEvent; | |||
| import android.view.View; | |||
| import android.view.inputmethod.InputMethodManager; | |||
| import android.widget.EditText; | |||
| import android.widget.ImageView; | |||
| import android.widget.Toast; | |||
| import com.blankj.utilcode.util.ToastUtils; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import com.handset.serialportsensor.utils.SPUtils; | |||
| public class LoginActivity extends BaseActivity implements SurfaceContract.ISerialView/*implements ServiceConnection, SerialService.OnReadValueCallback, SerialService.OnMateBaudRateCallback*/ { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private static int role = Constant.SENIOR_ROLE; | |||
| private static final int DIALOG_TIMEOUT = 30000; | |||
| private static final int READ_TIMEOUT = 3000; | |||
| private Boolean isReady = false; | |||
| private Integer baudRate; | |||
| private EditText etUserName; | |||
| private EditText etPwd; | |||
| private AlertDialog alertDialog; | |||
| private SurfacePresenter mPresenter; | |||
| private Handler mHandlerIdRead = new Handler(); | |||
| Handler mHandlerAlertDialog = new Handler(); | |||
| private Runnable mRunnableIdRead, mRunnableAlertDialog; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_login); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| findViewById(R.id.title_layout).setBackground(null); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setImageResource(R.mipmap.img_back); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| etPwd = findViewById(R.id.et_pwd); | |||
| etUserName = findViewById(R.id.et_user_name); | |||
| findViewById(R.id.btn_login).setOnClickListener((View view) -> login()); | |||
| mPresenter = new SurfacePresenter(this); | |||
| checkLoginStatus(); | |||
| } | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| } | |||
| @Override | |||
| protected void onStop() { | |||
| super.onStop(); | |||
| //mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| super.onDestroy(); | |||
| //mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); | |||
| } | |||
| @Override | |||
| public boolean onTouchEvent(MotionEvent event) { | |||
| InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); | |||
| if(im != null) { | |||
| View view = getCurrentFocus(); | |||
| if(view != null) { | |||
| im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); | |||
| } | |||
| } | |||
| return super.onTouchEvent(event); | |||
| } | |||
| private void login() { | |||
| if (checkoutLoginInfo()) { | |||
| Log.i(logTag, ("auth ok, go to setting view.")); | |||
| alertDialog = ToastHelper.showTipDialog((this), R.mipmap.img_loading, R.string.identifying); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> mPresenter.open(), (1000)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| mRunnableAlertDialog = () -> { | |||
| Log.i(logTag, ("alertDialog force close!")); | |||
| alertDialog.dismiss(); | |||
| }; | |||
| mHandlerAlertDialog.postDelayed(mRunnableAlertDialog, DIALOG_TIMEOUT); | |||
| } | |||
| } | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| runOnUiThread(() -> { | |||
| if (isOpen) { | |||
| mRunnableIdRead = () -> { | |||
| String cmd = genCmd(("FFFFFFFF"), Constant.Command.COMMAND_25); | |||
| Log.e(logTag, "login activity cmd: " + cmd); | |||
| mPresenter.write(cmd); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> { | |||
| Log.i(logTag, ("login fetching sensor no ready: " + isReady)); | |||
| if (!isReady) { | |||
| Log.e(logTag, ("login watch dog check, no data report!")); | |||
| runOnUiThread(() -> { | |||
| ToastUtils.showShort(R.string.test_id_error); | |||
| if(alertDialog.isShowing()) { | |||
| alertDialog.dismiss(); | |||
| } | |||
| mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); | |||
| LoginActivity.this.finish(); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().post(() -> { | |||
| mPresenter.close(); | |||
| }); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| }); | |||
| } else { | |||
| Log.i(logTag, ("login watch dog check, data report normally")); | |||
| } | |||
| }, (1000)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| //mPresenter.write("DDDDFFFFFFFF0025003E90"); | |||
| }; | |||
| mHandlerIdRead.postDelayed(mRunnableIdRead, READ_TIMEOUT); | |||
| } else { | |||
| Log.i(logTag, "port is closing!"); | |||
| } | |||
| }); | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| this.baudRate = baudRate; | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| if (rawData.getItemType() == RawData.TYPE_RECEIVE) { | |||
| String data = rawData.getMessage(); | |||
| Log.i(logTag, ("LoginActivity onSerialData: " + data)); | |||
| if (data.length() == 22) { | |||
| isReady = true; | |||
| alertDialog.dismiss(); | |||
| mHandlerAlertDialog.removeCallbacks(mRunnableAlertDialog); | |||
| mPresenter.close(); | |||
| boolean isRoot = AccountManager.get().getUserId().equals("root"); | |||
| boolean sensorThirdEnable = SPUtils.getInstance(this).get(("sensor_third_enable"), (false)); | |||
| boolean isOwn = isOwnSensor(data); | |||
| Log.i(logTag, ("onSerialData: isRoot: " + isRoot + ", sensorThirdEnable: " + sensorThirdEnable + ", isOwn: " + isOwn)); | |||
| int roleType = (isRoot || sensorThirdEnable || isOwn) ? Constant.SENIOR_ROLE : Constant.NOT_CONNECTED_ROLE; | |||
| SensorSettingsActivity.open(this.baudRate, roleType, data.substring(4, 12), (LoginActivity.this)); | |||
| LoginActivity.this.finish(); | |||
| } | |||
| } | |||
| } | |||
| private boolean isOwnSensor(String data) { | |||
| byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); | |||
| int no = ((bytes[2] & 0xff) * 100 + (bytes[3] & 0xff)) * 10000 + ((bytes[4] & 0xff) << 8) + (bytes[5] & 0xff); | |||
| String s = "00000000".concat(String.valueOf(no)); | |||
| String sensorNo = s.substring(s.length() - 8); | |||
| Log.i(logTag, ("isThirdSensor: " + sensorNo + ", position[4]: " + sensorNo.charAt(4))); | |||
| return sensorNo.charAt(4) == '1'; | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| runOnUiThread(() -> { | |||
| ToastUtils.showShort(R.string.test_btl_error); | |||
| mPresenter.close(); | |||
| alertDialog.dismiss(); | |||
| LoginActivity.this.finish(); | |||
| }); | |||
| } | |||
| private void checkLoginStatus() { | |||
| if (AccountManager.get().isLogin()) { | |||
| login(); | |||
| } | |||
| } | |||
| private boolean checkoutLoginInfo() { | |||
| if (AccountManager.get().isLogin()) { | |||
| return true; | |||
| } | |||
| String pwd = etPwd.getText().toString(); | |||
| String username = etUserName.getText().toString(); | |||
| if (TextUtils.isEmpty(username)) { | |||
| Toast.makeText((this), "登录失败,用户名为空", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (TextUtils.isEmpty(pwd)) { | |||
| Toast.makeText((this), "登录失败,密码为空", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| String pwdSp = SPUtils.getInstance(this).get(username); | |||
| Log.i(logTag, "pwdSp: " + pwdSp + ", username: " + username); | |||
| if (TextUtils.isEmpty(pwdSp)) { | |||
| if ("root".equals(username) && "root".equals(pwd)) { | |||
| Toast.makeText((this), "root 登录成功", Toast.LENGTH_SHORT).show(); | |||
| AccountManager.get().login("root", "root"); | |||
| return true; | |||
| } | |||
| if ("admin".equals(username) && "admin".equals(pwd)) { | |||
| AccountManager.get().login("admin", "admin"); | |||
| Toast.makeText((this), "admin 登录成功", Toast.LENGTH_SHORT).show(); | |||
| return true; | |||
| } | |||
| } else { | |||
| if (pwdSp.equals(pwd)) { | |||
| AccountManager.get().login(username, pwdSp); | |||
| Toast.makeText((this), username + " 登录成功", Toast.LENGTH_SHORT).show(); | |||
| return true; | |||
| } | |||
| } | |||
| Toast.makeText((this), "登录失败,用户名或密码错误", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| } | |||
| @ -0,0 +1,624 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.Manifest; | |||
| import android.app.AlertDialog; | |||
| import android.content.Intent; | |||
| import android.content.pm.PackageManager; | |||
| import android.os.Build; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.support.v4.app.ActivityCompat; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.widget.Button; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.blankj.utilcode.util.ToastUtils; | |||
| import com.google.common.base.Splitter; | |||
| import com.google.gson.Gson; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.bean.MetaData; | |||
| import com.handset.serialportsensor.bean.ThresholdBean; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.Slog; | |||
| import com.handset.serialportsensor.utils.SpUtil; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import com.handset.serialportsensor.utils.PersistHelper; | |||
| import com.handset.serialportsensor.utils.StatusBarUtils; | |||
| import com.handset.serialportsensor.utils.Utils; | |||
| import com.handset.serialportsensor.widget.DashBoard; | |||
| import java.text.DecimalFormat; | |||
| public class Main2Activity extends BaseActivity implements SurfaceContract.ISerialView { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private Integer baudRate = 38400; | |||
| private final static String FLOAT_TYPE = "0.00"; | |||
| private final static int STARTING_TIMEOUT = 3000; | |||
| private final static int SAVING_TIMEOUT = 7000; | |||
| private final static int WATCHDOG_TIMEOUT = 1000; | |||
| private static boolean readBtnStatusOpen = false; | |||
| private final static String DEFAULT_VALUE = "- - -"; | |||
| private static ThresholdBean thresholdBean; | |||
| private SurfacePresenter mPresenter; | |||
| private static MetaData metaData = MetaData.builder().build(); | |||
| private DashBoard mDashBoardTemperature; | |||
| private DashBoard mDashBoardHumidity; | |||
| private DashBoard mDashBoardInnerPressure; | |||
| private DashBoard mDashBoardOuterPressure; | |||
| private DashBoard mDashBoardDiffPressure; | |||
| private static String[] PERMISSIONS_STORAGE = { | |||
| Manifest.permission.READ_EXTERNAL_STORAGE, | |||
| Manifest.permission.WRITE_EXTERNAL_STORAGE | |||
| }; | |||
| private Handler mHandlerResetReadBtn = new Handler(); | |||
| private Runnable mRunnableResetReadBtn; | |||
| private Handler mHandlerSaveClose = new Handler(); | |||
| private Runnable mRunnableSaveClose; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| StatusBarUtils.setTranslucentStatus(this); | |||
| StatusBarUtils.setStatusColor((this), (false), (true), R.color.white); | |||
| setContentView(R.layout.activity_main2); | |||
| initView(); | |||
| disableSettingBtn(); | |||
| thresholdBean = new Gson().fromJson((String) SpUtil.get((this), Constant.THRESHOLD_KEY, ("")), ThresholdBean.class); | |||
| if (thresholdBean == null) { | |||
| Log.i(logTag, ("onCreate: thresholdBean null")); | |||
| thresholdBean = ThresholdBean.builder() | |||
| .temperatureFloor("-40").temperatureCeiling("65") | |||
| .humidityFloor("0").humidityCeiling("100") | |||
| .innerPressureFloor("80").innerPressureCeiling("150") | |||
| .outerPressureFloor("80").outerPressureCeiling("150") | |||
| .diffPressureFloor("-20").diffPressureCeiling("30") | |||
| .build(); | |||
| } | |||
| SpUtil.put((this), Constant.THRESHOLD_KEY, new Gson().toJson(thresholdBean)); | |||
| Slog.i(logTag, ("onCreate, thresholdBean value: " + thresholdBean)); | |||
| //Slog.save(logTag, ("onCreate, thresholdBean value: " + thresholdBean)); | |||
| mPresenter = new SurfacePresenter((this)); | |||
| mPresenter.initBLNStatus('0'); | |||
| if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { | |||
| if (ActivityCompat.checkSelfPermission((this), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { | |||
| ActivityCompat.requestPermissions((this), PERMISSIONS_STORAGE, (1)); | |||
| } | |||
| } | |||
| // emulator | |||
| //initEmulator(); | |||
| } | |||
| @Override | |||
| protected void onPause() { | |||
| super.onPause(); | |||
| Log.i(logTag, ("onPause, close bln")); | |||
| } | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| Slog.i(logTag, ("onResume, open bln")); | |||
| thresholdBean = new Gson().fromJson((String) SpUtil.get((this), Constant.THRESHOLD_KEY, ("")), ThresholdBean.class); | |||
| if (thresholdBean == null) { | |||
| Log.i(logTag, ("onResume: thresholdBean null")); | |||
| } | |||
| if (thresholdBean != null) { | |||
| if (mDashBoardTemperature != null && mDashBoardTemperature.textStart != null) { | |||
| mDashBoardTemperature.textStart = thresholdBean.temperatureFloor; | |||
| } | |||
| if (mDashBoardTemperature != null && mDashBoardTemperature.textEnd != null) { | |||
| mDashBoardTemperature.textEnd = thresholdBean.temperatureCeiling; | |||
| } | |||
| // | |||
| if (mDashBoardHumidity != null && mDashBoardHumidity.textStart != null) { | |||
| mDashBoardHumidity.textStart = thresholdBean.humidityFloor; | |||
| } | |||
| if (mDashBoardHumidity != null && mDashBoardHumidity.textEnd != null) { | |||
| mDashBoardHumidity.textEnd = thresholdBean.humidityCeiling; | |||
| } | |||
| // | |||
| if (mDashBoardInnerPressure != null && mDashBoardInnerPressure.textStart != null) { | |||
| mDashBoardInnerPressure.textStart = thresholdBean.innerPressureFloor; | |||
| } | |||
| if (mDashBoardInnerPressure != null && mDashBoardInnerPressure.textEnd != null) { | |||
| mDashBoardInnerPressure.textEnd = thresholdBean.innerPressureCeiling; | |||
| } | |||
| // | |||
| if (mDashBoardOuterPressure != null && mDashBoardOuterPressure.textStart != null) { | |||
| mDashBoardOuterPressure.textStart = thresholdBean.outerPressureFloor; | |||
| } | |||
| if (mDashBoardOuterPressure != null && mDashBoardOuterPressure.textEnd != null) { | |||
| mDashBoardOuterPressure.textEnd = thresholdBean.outerPressureCeiling; | |||
| } | |||
| // | |||
| if (mDashBoardDiffPressure != null && mDashBoardDiffPressure.textStart != null) { | |||
| mDashBoardDiffPressure.textStart = thresholdBean.diffPressureFloor; | |||
| } | |||
| if (mDashBoardDiffPressure != null && mDashBoardDiffPressure.textEnd != null) { | |||
| mDashBoardDiffPressure.textEnd = thresholdBean.diffPressureCeiling; | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| super.onDestroy(); | |||
| Log.i(logTag, ("main activity destroy")); | |||
| mHandlerResetReadBtn.removeCallbacks(mRunnableResetReadBtn); | |||
| mPresenter.close(); | |||
| mPresenter.onDestroy(); | |||
| } | |||
| private void initView() { | |||
| mDashBoardTemperature = findViewById(R.id.dashboard_temperature); | |||
| mDashBoardHumidity = findViewById(R.id.dashboard_humidity); | |||
| mDashBoardInnerPressure = findViewById(R.id.dashboard_inner_pressure); | |||
| mDashBoardOuterPressure = findViewById(R.id.dashboard_outer_pressure); | |||
| mDashBoardDiffPressure = findViewById(R.id.dashboard_diff_pressure); | |||
| } | |||
| @SuppressWarnings(value = "unused") | |||
| private void initEmulator() { | |||
| mDashBoardTemperature.setSecondText("26.97"); | |||
| mDashBoardHumidity.setSecondText("31.61"); | |||
| mDashBoardInnerPressure.setSecondText("102.55"); | |||
| mDashBoardDiffPressure.setSecondText("-0.76"); | |||
| mDashBoardOuterPressure.setSecondText("103.32"); | |||
| } | |||
| private void disableSettingBtn() { | |||
| ImageView ivSettings = findViewById(R.id.title_back); | |||
| ivSettings.setImageResource(R.mipmap.settings_disable); | |||
| ivSettings.setEnabled(false); | |||
| } | |||
| private void enableSettingBtn() { | |||
| ImageView ivSettings = findViewById(R.id.title_back); | |||
| ivSettings.setImageResource(R.mipmap.settings); | |||
| ivSettings.setEnabled(true); | |||
| } | |||
| private void disableHistoryBtn() { | |||
| ImageView ivSettings = findViewById(R.id.iv_start); | |||
| ivSettings.setImageResource(R.mipmap.history_disable); | |||
| ivSettings.setEnabled(false); | |||
| } | |||
| private void enableHistoryBtn() { | |||
| ImageView ivSettings = findViewById(R.id.iv_start); | |||
| ivSettings.setImageResource(R.mipmap.history); | |||
| ivSettings.setEnabled(true); | |||
| } | |||
| public void onClickBtnRead(View view) { | |||
| clearDashBoard(); | |||
| if (!readBtnStatusOpen) { | |||
| disableSettingBtn(); | |||
| disableHistoryBtn(); | |||
| readBtnToStartingState(); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().post(() -> mPresenter.open()); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| } else { | |||
| mPresenter.close(); | |||
| resetStatus(); | |||
| showStopTestDialog(); | |||
| } | |||
| } | |||
| private void showStopTestDialog() { | |||
| ToastHelper.showSaveSensorDialog((this), new ToastHelper.OnDialogClickListener() { | |||
| @Override | |||
| public void onOKClickListener(View view) { | |||
| PersistHelper.endTest(); | |||
| showSavingDataDialog(); | |||
| } | |||
| @Override | |||
| public void onCancelClickListener(View view) { | |||
| PersistHelper.endTest((false)); | |||
| showCancelingDataDialog(); | |||
| } | |||
| }); | |||
| } | |||
| private void showSavingDataDialog() { | |||
| runOnUiThread(() -> { | |||
| AlertDialog alertDialog = ToastHelper.showTipDialog((Main2Activity.this), R.mipmap.img_loading, R.string.saving); | |||
| mRunnableSaveClose = alertDialog::dismiss; | |||
| mHandlerSaveClose.postDelayed(mRunnableSaveClose, SAVING_TIMEOUT); | |||
| }); | |||
| } | |||
| private void showCancelingDataDialog() { | |||
| runOnUiThread(() -> { | |||
| AlertDialog alertDialog = ToastHelper.showTipDialog((Main2Activity.this), R.mipmap.img_loading, R.string.canceling); | |||
| mRunnableSaveClose = alertDialog::dismiss; | |||
| mHandlerSaveClose.postDelayed(mRunnableSaveClose, SAVING_TIMEOUT); | |||
| }); | |||
| } | |||
| public void onClickSettingBtn(View view) { | |||
| startActivity(new Intent((Main2Activity.this), LoginActivity.class)); | |||
| } | |||
| public void onClickHistoryBtn(View view) { | |||
| startActivity(new Intent((Main2Activity.this), HistoryActivity.class)); | |||
| } | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| runOnUiThread(() -> { | |||
| readBtnStatusOpen = isOpen; | |||
| if (isOpen) { | |||
| mRunnableResetReadBtn = () -> { | |||
| mPresenter.write(genCmd(("FFFFFFFF"), Constant.Command.COMMAND_25)); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> { | |||
| Log.i(logTag, ("metaData sensorNo: " + metaData.getSensorNo())); | |||
| if (TextUtils.isEmpty(metaData.getSensorNo())) { | |||
| Log.e(logTag, ("watch dog check, no data report!")); | |||
| runOnUiThread(() -> { | |||
| ToastUtils.showShort(R.string.test_id_error); | |||
| new Thread( | |||
| () -> { | |||
| Looper.prepare(); | |||
| new Handler().post(() -> { | |||
| mPresenter.close(); | |||
| }); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| }); | |||
| } else { | |||
| Log.i(logTag, ("watch dog check, data report normally")); | |||
| runOnUiThread(this::readBtnToStopState); | |||
| } | |||
| }, WATCHDOG_TIMEOUT); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| }; | |||
| mHandlerResetReadBtn.postDelayed(mRunnableResetReadBtn, STARTING_TIMEOUT); | |||
| } else { | |||
| Log.i(logTag, ("Testing closing")); | |||
| metaData.resetData(); | |||
| readBtnToState((false)); | |||
| //enableSettingBtn(); | |||
| enableHistoryBtn(); | |||
| } | |||
| }); | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| this.baudRate = baudRate; | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| String message = rawData.getMessage(); | |||
| boolean res = rawData.getItemType() == RawData.TYPE_SEND | |||
| ? doSendMessage(message) | |||
| : doReceiveMessage(message); | |||
| Log.v(logTag, ("res: " + res)); | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| runOnUiThread(() -> { | |||
| ToastUtils.showShort(R.string.test_btl_error); | |||
| readBtnToOriginState(); | |||
| //enableSettingBtn(); | |||
| enableHistoryBtn(); | |||
| }); | |||
| } | |||
| private void setMakerNoView(int text) { | |||
| ((TextView) (findViewById(R.id.tv_maker))).setText(String.valueOf(text)); | |||
| } | |||
| private void setSensorNoView(String text) { | |||
| //String textCooked = text.substring(0, 4) + text.substring(5); | |||
| ((TextView) (findViewById(R.id.tv_sensor_no))).setText(text); | |||
| } | |||
| private void setEggNoView(String text) { | |||
| ((TextView) (findViewById(R.id.tv_egg_no))).setText(text); | |||
| } | |||
| private void setEggTypeView(String text) { | |||
| ((TextView) (findViewById(R.id.tv_egg_type))).setText(text); | |||
| } | |||
| private void setConeNoView(String text) { | |||
| ((TextView) (findViewById(R.id.tv_cone_no))).setText(text); | |||
| } | |||
| private void setConeUsedTimesView(String text) { | |||
| ((TextView) (findViewById(R.id.tv_cone_used_times))).setText(text); | |||
| } | |||
| private boolean doReceiveMessage(String contain) { | |||
| try { | |||
| Log.i(logTag, ("doReceiveMessage: " + contain)); | |||
| if (contain.length() < 100) { | |||
| doCalcBasicData(contain); | |||
| } else { | |||
| metaData.resetData20Degree(); | |||
| for (String data : Splitter.fixedLength(30).split(contain)) { | |||
| metaData.doCalcMeta(data); | |||
| } | |||
| metaData.doCalcMetaEx(); | |||
| boolean valid = metaData.isValid(); | |||
| Log.i(logTag, "valid: " + valid); | |||
| if (!valid) { | |||
| //setStatusAbnormal(); | |||
| return false; | |||
| } | |||
| doPersist(metaData); | |||
| setDashBoard(metaData); | |||
| //setStatusNormal(); | |||
| } | |||
| return true; | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| } | |||
| private boolean doSendMessage(String message) { | |||
| Log.v(logTag, ("Activity send message: " + message)); | |||
| return true; | |||
| } | |||
| private void doCalcBasicData(String data) { | |||
| byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); | |||
| switch (bytes[7] & 0xff) { | |||
| case Constant.Command.COMMAND_26: | |||
| metaData.setMakerId(getMakerId(bytes)); | |||
| metaData.setSensorNo(getSensorNo(bytes)); | |||
| metaData.setSensorNoRadix(getSensorNoRadix(bytes)); | |||
| setMakerNoView(metaData.getMakerId()); | |||
| setSensorNoView(Utils.getSensorNoShow(metaData.getSensorNo())); | |||
| Log.e(logTag, "sensorNo: " + metaData.getSensorNo()); | |||
| PersistHelper.genItem(Integer.valueOf(metaData.getSensorNo()), String.valueOf(this.baudRate)); | |||
| //mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_27)); | |||
| break; | |||
| case Constant.Command.COMMAND_28: | |||
| mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_30)); | |||
| break; | |||
| case Constant.Command.COMMAND_31: | |||
| metaData.setEggNo(getEggNo(bytes)); | |||
| setEggNoView(metaData.getEggNo()); | |||
| PersistHelper.saveEggID(metaData.getEggNo()); | |||
| mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_3E)); | |||
| break; | |||
| case Constant.Command.COMMAND_3F: | |||
| metaData.setEggType(getEggType(bytes)); | |||
| setEggTypeView(metaData.getEggType()); | |||
| PersistHelper.saveEggType(metaData.getEggType()); | |||
| mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_34)); | |||
| break; | |||
| case Constant.Command.COMMAND_35: | |||
| metaData.setConeNo(getConeNo(bytes)); | |||
| setConeNoView(metaData.getConeNo()); | |||
| PersistHelper.saveConeNo(metaData.getConeNo()); | |||
| Log.i(logTag, "sensorNoRadix: " + metaData.getSensorNoRadix()); | |||
| mPresenter.write(genCmd(metaData.getSensorNoRadix(), Constant.Command.COMMAND_38)); | |||
| break; | |||
| case Constant.Command.COMMAND_39: | |||
| metaData.setConeUsedTimes(getConeUsedTimes(bytes)); | |||
| setConeUsedTimesView(metaData.getConeUsedTimes()); | |||
| PersistHelper.saveConeUsedTimes(metaData.getConeUsedTimes()); | |||
| break; | |||
| } | |||
| } | |||
| private int getMakerId(byte[] bytes) { | |||
| int i = ((bytes[4] & 0xff) << 8) | (bytes[5] & 0xff); | |||
| String s = "0000".concat(String.valueOf(i)); | |||
| String s2 = s.substring(s.length() - 4); | |||
| return Integer.valueOf(s2.substring(0, 1)); | |||
| } | |||
| private String getSensorNo(byte[] bytes) { | |||
| int no = ((bytes[2] & 0xff) * 100 + (bytes[3] & 0xff)) * 10000 + ((bytes[4] & 0xff) << 8) + (bytes[5] & 0xff); | |||
| String s = "00000000".concat(String.valueOf(no)); | |||
| return s.substring(s.length() - 8); | |||
| } | |||
| private String getSensorNoRadix(byte[] bytes) { | |||
| int len = 4; | |||
| byte[] dest = new byte[len]; | |||
| System.arraycopy(bytes, 2, dest, 0, len); | |||
| return ByteUtils.bytesToHexStr(dest); | |||
| } | |||
| private String getEggNo(byte[] bytes) { | |||
| int len = bytes[8]; | |||
| byte[] dest = new byte[len]; | |||
| System.arraycopy(bytes, 9, dest, 0, len); | |||
| ByteUtils.bytesToAscii(dest); | |||
| return ByteUtils.bytesToAscii(dest); | |||
| } | |||
| private String getEggType(byte[] bytes) { | |||
| int len = bytes[8]; | |||
| byte[] dest = new byte[len]; | |||
| System.arraycopy(bytes, 9, dest, 0, len); | |||
| ByteUtils.bytesToAscii(dest); | |||
| return ByteUtils.bytesToAscii(dest); | |||
| } | |||
| private String getConeNo(byte[] bytes) { | |||
| int len = bytes[8]; | |||
| byte[] dest = new byte[len]; | |||
| System.arraycopy(bytes, 9, dest, 0, len); | |||
| ByteUtils.bytesToAscii(dest); | |||
| return ByteUtils.bytesToAscii(dest); | |||
| } | |||
| private String getConeUsedTimes(byte[] bytes) { | |||
| int len = bytes[8]; | |||
| byte[] dest = new byte[len]; | |||
| System.arraycopy(bytes, 9, dest, 0, len); | |||
| ByteUtils.bytesToAscii(dest); | |||
| return ByteUtils.bytesToAscii(dest); | |||
| } | |||
| private void clearDashBoard() { | |||
| mDashBoardTemperature.setSecondText(DEFAULT_VALUE); | |||
| mDashBoardHumidity.setSecondText(DEFAULT_VALUE); | |||
| mDashBoardInnerPressure.setSecondText(DEFAULT_VALUE); | |||
| mDashBoardOuterPressure.setSecondText(DEFAULT_VALUE); | |||
| mDashBoardDiffPressure.setSecondText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_20degree_humidity))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_20degree_inner_press))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_maker))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_sensor_no))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_egg_no))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_egg_type))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_cone_no))).setText(DEFAULT_VALUE); | |||
| ((TextView) (findViewById(R.id.tv_cone_used_times))).setText(DEFAULT_VALUE); | |||
| } | |||
| private void setDashBoard(MetaData metaData) { | |||
| boolean isNormal = true; | |||
| if (thresholdBean == null) { | |||
| Log.i(logTag, "thresholdBean is null"); | |||
| } | |||
| if (metaData.getTemperature() < Float.valueOf(thresholdBean.getTemperatureFloor()) || metaData.getTemperature() > Float.valueOf(thresholdBean.getTemperatureCeiling())) { | |||
| isNormal = false; | |||
| mDashBoardTemperature.setSecondText(metaData.getTemperature(), (false)); | |||
| } else { | |||
| mDashBoardTemperature.setSecondText(metaData.getTemperature(), (true)); | |||
| } | |||
| if (metaData.getHumidity() < Float.valueOf(thresholdBean.getHumidityFloor()) || metaData.getHumidity() > Float.valueOf(thresholdBean.getHumidityCeiling())) { | |||
| isNormal = false; | |||
| mDashBoardHumidity.setSecondText(metaData.getHumidity(), (false)); | |||
| } else { | |||
| mDashBoardHumidity.setSecondText(metaData.getHumidity(), (true)); | |||
| } | |||
| if (metaData.getInnerPressure() < Float.valueOf(thresholdBean.getInnerPressureFloor()) || metaData.getInnerPressure() > Float.valueOf(thresholdBean.getInnerPressureCeiling())) { | |||
| isNormal = false; | |||
| mDashBoardInnerPressure.setSecondText(metaData.getInnerPressure(), (false)); | |||
| } else { | |||
| mDashBoardInnerPressure.setSecondText(metaData.getInnerPressure(), (true)); | |||
| } | |||
| if (metaData.getOuterPressure() < Float.valueOf(thresholdBean.getOuterPressureFloor()) || metaData.getOuterPressure() > Float.valueOf(thresholdBean.getOuterPressureCeiling())) { | |||
| isNormal = false; | |||
| mDashBoardOuterPressure.setSecondText(metaData.getOuterPressure(), (false)); | |||
| } else { | |||
| mDashBoardOuterPressure.setSecondText(metaData.getOuterPressure(), (true)); | |||
| } | |||
| if (metaData.getDiffPressure() < Float.valueOf(thresholdBean.getDiffPressureFloor()) || metaData.getDiffPressure() > Float.valueOf(thresholdBean.getDiffPressureCeiling())) { | |||
| isNormal = false; | |||
| mDashBoardDiffPressure.setSecondText(metaData.getDiffPressure(), (false)); | |||
| } else { | |||
| mDashBoardDiffPressure.setSecondText(metaData.getDiffPressure(), (true)); | |||
| } | |||
| ((TextView) (findViewById(R.id.tv_20degree_humidity))).setText(new DecimalFormat(FLOAT_TYPE).format(metaData.getDegree20Humidity())); | |||
| ((TextView) (findViewById(R.id.tv_20degree_inner_press))).setText(new DecimalFormat(FLOAT_TYPE).format(metaData.getDegree20Pressure())); | |||
| if (isNormal) { | |||
| setStatusNormal(); | |||
| } else { | |||
| setStatusAbnormal(); | |||
| } | |||
| } | |||
| private void setStatusNormal() { | |||
| ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.param_black_color)); | |||
| findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_green_round); | |||
| ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.status_grey)); | |||
| findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_grey_round); | |||
| } | |||
| private void setStatusAbnormal() { | |||
| ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.status_grey)); | |||
| findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_grey_round); | |||
| ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.param_black_color)); | |||
| findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_red_round); | |||
| } | |||
| private void resetStatus() { | |||
| ((TextView) (findViewById(R.id.tv_main_status_normal))).setTextColor(getResources().getColor(R.color.param_grey_color)); | |||
| findViewById(R.id.tv_main_status_normal_round).setBackgroundResource(R.drawable.shape_status_grey_round); | |||
| ((TextView) (findViewById(R.id.tv_main_status_err))).setTextColor(getResources().getColor(R.color.status_grey)); | |||
| findViewById(R.id.tv_main_status_err_round).setBackgroundResource(R.drawable.shape_status_grey_round); | |||
| } | |||
| private void readBtnToOriginState() { | |||
| findViewById(R.id.btn_read).setEnabled(true); | |||
| findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_start_btn_new); | |||
| ((Button) findViewById(R.id.btn_read)).setText(R.string.start_test); | |||
| } | |||
| private void readBtnToStopState() { | |||
| findViewById(R.id.btn_read).setEnabled(true); | |||
| findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_stop_btn_new); | |||
| ((Button) findViewById(R.id.btn_read)).setText(R.string.stop_test); | |||
| } | |||
| private void readBtnToStartingState() { | |||
| findViewById(R.id.btn_read).setBackgroundResource(R.drawable.bg_read_btn_starting); | |||
| ((Button) findViewById(R.id.btn_read)).setText(R.string.read_btn_starting); | |||
| findViewById(R.id.btn_read).setEnabled(false); | |||
| } | |||
| private void readBtnToState(boolean isOpen) { | |||
| findViewById(R.id.btn_read).setEnabled(true); | |||
| findViewById(R.id.btn_read).setBackgroundResource(isOpen ? R.drawable.bg_stop_btn_new : R.drawable.bg_start_btn_new); | |||
| ((Button) findViewById(R.id.btn_read)).setText(isOpen ? R.string.stop_test : R.string.start_test); | |||
| } | |||
| private void doPersist(MetaData metaData) { | |||
| PersistHelper.save(metaData.getTemperature(), Constant.Command.COMMAND_29); | |||
| PersistHelper.save(metaData.getInnerPressure(), Constant.Command.COMMAND_2A); | |||
| PersistHelper.save(metaData.getHumidity(), Constant.Command.COMMAND_2B); | |||
| PersistHelper.save(metaData.getOuterPressure(), Constant.Command.COMMAND_2C); | |||
| PersistHelper.save(metaData.getDiffPressure(), Constant.Command.COMMAND_2D); | |||
| PersistHelper.save(metaData.getDegree20Humidity(), Constant.Command.COMMAND_2E); | |||
| PersistHelper.save(metaData.getDegree20Pressure(), Constant.Command.COMMAND_2F); | |||
| } | |||
| } | |||
| @ -0,0 +1,77 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.os.Bundle; | |||
| import android.text.TextUtils; | |||
| import android.view.View; | |||
| import android.widget.EditText; | |||
| import android.widget.ImageView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.utils.SPUtils; | |||
| public class PasswordResetActivity extends BaseActivity { | |||
| private EditText etOriginal; | |||
| private EditText etNew; | |||
| private EditText etRepeat; | |||
| LinearLayout ll_old_pas; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_reset_password); | |||
| initView(); | |||
| } | |||
| boolean showAdmin; | |||
| private void initView() { | |||
| initTitle(); | |||
| etOriginal = findViewById(R.id.et_original_password); | |||
| etNew = findViewById(R.id.et_new_password); | |||
| etRepeat = findViewById(R.id.et_repeat_password); | |||
| ll_old_pas = findViewById(R.id.ll_old_pas); | |||
| TextView btnSave = findViewById(R.id.btn_save); | |||
| btnSave.setOnClickListener((View view) -> save()); | |||
| showAdmin = "admin".equals(AccountManager.get().getUserId()); | |||
| ll_old_pas.setVisibility(showAdmin ? View.VISIBLE : View.GONE); | |||
| } | |||
| private void save() { | |||
| String pwdOld = etOriginal.getText().toString(); | |||
| String etn = etNew.getText().toString(); | |||
| String etR = etRepeat.getText().toString(); | |||
| if (AccountManager.get().isLogin()) { | |||
| if (showAdmin) { | |||
| String pwdOldTrue = SPUtils.getInstance(this).get("admin"); | |||
| if (!TextUtils.isEmpty(pwdOldTrue) && !pwdOld.equals(pwdOldTrue)) { | |||
| Toast.makeText(this, getString(R.string.old_pwd_wrong), Toast.LENGTH_SHORT).show(); | |||
| return; | |||
| } | |||
| } | |||
| if (TextUtils.isEmpty(etn) || TextUtils.isEmpty(etR)) { | |||
| Toast.makeText((this), getString(R.string.new_pwd_empty), Toast.LENGTH_SHORT).show(); | |||
| } else if (!etn.equals(etR)) { | |||
| Toast.makeText((this), getString(R.string.new_pwd_not_same), Toast.LENGTH_SHORT).show(); | |||
| } else { | |||
| SPUtils.getInstance(this).put("admin", etR); | |||
| Toast.makeText((this), getString(R.string.pwd_change_success), Toast.LENGTH_SHORT).show(); | |||
| finish(); | |||
| } | |||
| } else { | |||
| Toast.makeText((this), getString(R.string.pwd_login_first), Toast.LENGTH_SHORT).show(); | |||
| } | |||
| } | |||
| private void initTitle() { | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| tvTitle.setText(R.string.reset_password_title); | |||
| } | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| public interface SPKey { | |||
| String SU_PATH = "su_path"; | |||
| String SERIAL_PORT = "serial_port"; | |||
| String BAUD_RATE = "baud_rate"; | |||
| String DATA_BITS = "data_bits"; | |||
| String CHECK_DIGIT = "check_digit"; | |||
| String STOP_BIT = "stop_bit"; | |||
| String FLOW_CONTROL = "flow_control"; | |||
| String SETTING_RECEIVE_TYPE = "receive_type"; | |||
| String SETTING_RECEIVE_SHOW_TIME = "setting_receive_show_time"; | |||
| String SETTING_RECEIVE_SHOW_SEND = "setting_receive_show_send"; | |||
| String SETTING_SEND_TYPE = "setting_send_type"; | |||
| String SETTING_SEND_REPEAT = "setting_send_repeat"; | |||
| String SETTING_SEND_DURING = "setting_send_during"; | |||
| String SEND_HISTORY = "send_history"; | |||
| } | |||
| @ -0,0 +1,441 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.annotation.SuppressLint; | |||
| import android.app.AlertDialog; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.os.Handler; | |||
| import android.os.Looper; | |||
| import android.os.Message; | |||
| import android.provider.Settings; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.v7.widget.LinearLayoutManager; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.adapter.SettingsAdapter; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportsensor.bean.SettingsItem; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.presenter.SurfaceContract; | |||
| import com.handset.serialportsensor.presenter.SurfacePresenter; | |||
| import com.handset.serialportsensor.utils.DateUtils; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| import com.handset.serialportsensor.utils.ExcelMa; | |||
| import com.handset.serialportsensor.utils.PersistHelper; | |||
| import com.handset.serialportsensor.view.ExportProgressDialog; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.util.ArrayList; | |||
| import java.util.Arrays; | |||
| import java.util.List; | |||
| import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM; | |||
| public class SensorSettingsActivity extends BaseActivity implements SettingsAdapter.OnItemClickListener, SurfaceContract.ISerialView { | |||
| private final static String logTag = "HANDSET-JE002-EX"; | |||
| private String sensorId; | |||
| private Integer baudRate; | |||
| private AlertDialog resetDialog; | |||
| private ExcelMa mExcelMa = new ExcelMa(); | |||
| private SurfacePresenter mPresenter = new SurfacePresenter((this)); | |||
| private int[] iconsAdmin = new int[]{ | |||
| R.mipmap.ic_settings1, R.mipmap.ic_settings2, R.mipmap.ic_settings3, | |||
| R.mipmap.ic_settings4, R.mipmap.ic_settings5, R.mipmap.ic_settings6, R.mipmap.ic_settings7, | |||
| R.mipmap.ic_settings8, R.mipmap.ic_settings9, R.mipmap.ic_settings9, R.mipmap.ic_settings9 | |||
| }; | |||
| private String[] namesAdmin = new String[]{"波特率设置", "阈值设置", "弹筒信息", "数据导出", "数据恢复", "设置系统时间", "重置密码"}; | |||
| private int[] mPositionAdmin = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | |||
| private int[] iconsRoot = new int[]{ | |||
| R.mipmap.ic_settings7, R.mipmap.ic_settings8, R.mipmap.img_right, | |||
| R.mipmap.ic_settings2, R.mipmap.ic_settings9 | |||
| }; | |||
| private String[] namesRoot = new String[]{"重置密码", "恢复传感器出厂设置", "第三方传感器弹筒信息开关", "传感器ID设置", "查看操作日志"}; | |||
| private int[] mPositionRoot = new int[]{6, 7, 8, 9, 10}; | |||
| public static void open(Integer baudRate, Integer role, String sensorId, Context context) { | |||
| Intent intent = new Intent(context, SensorSettingsActivity.class); | |||
| intent.putExtra(Constant.ROLE_KEY, role); | |||
| Log.e(logTag, "sensorId 444: " + sensorId); | |||
| intent.putExtra(Constant.BAUD_RATE, baudRate); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| context.startActivity(intent); | |||
| } | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_sensor_settings); | |||
| initView(); | |||
| } | |||
| @Override | |||
| protected void onResume() { | |||
| super.onResume(); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| super.onDestroy(); | |||
| } | |||
| private void initView() { | |||
| initTitle(); | |||
| RecyclerView recyclerView = findViewById(R.id.recycle_view); | |||
| recyclerView.setLayoutManager(new LinearLayoutManager((this))); | |||
| Intent intent = getIntent(); | |||
| int role = Constant.NOT_CONNECTED_ROLE; | |||
| if (intent != null) { | |||
| role = intent.getIntExtra(Constant.ROLE_KEY, Constant.NOT_CONNECTED_ROLE); | |||
| baudRate = intent.getIntExtra(Constant.BAUD_RATE, (38400)); | |||
| sensorId = intent.getStringExtra(Constant.SENSOR_ID); | |||
| Log.i(logTag, ("hex string sensorId: " + sensorId)); | |||
| } | |||
| ArrayList<SettingsItem> items = new ArrayList<>(); | |||
| Log.i(logTag, ("accountId: " + AccountManager.get().getUserId())); | |||
| if (AccountManager.get().getUserId().equals("admin")) { | |||
| for (int i = 0; i < namesAdmin.length; i++) { | |||
| items.add(new SettingsItem(namesAdmin[i], iconsAdmin[i], mPositionAdmin[i])); | |||
| } | |||
| } else { | |||
| for (int i = 0; i < namesRoot.length; i++) { | |||
| items.add(new SettingsItem(namesRoot[i], iconsRoot[i], mPositionRoot[i])); | |||
| } | |||
| } | |||
| SettingsAdapter adapter = new SettingsAdapter(items, role); | |||
| adapter.setOnItemClickListener(this); | |||
| recyclerView.setAdapter(adapter); | |||
| findViewById(R.id.btn_logout).setOnClickListener((View v) -> { | |||
| AccountManager.get().logout(); | |||
| finish(); | |||
| startActivity(new Intent((SensorSettingsActivity.this), LoginActivity.class)); | |||
| }); | |||
| } | |||
| private void initTitle() { | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| tvTitle.setText(R.string.sensor_settings_title); | |||
| } | |||
| @Override | |||
| public void onItemClick(View view, int position) { | |||
| int id = mPositionAdmin[position]; | |||
| if (AccountManager.get().getUserId().equals("root")) { | |||
| id = mPositionRoot[position]; | |||
| } | |||
| Intent intent; | |||
| switch (id) { | |||
| case 0: | |||
| intent = new Intent((SensorSettingsActivity.this), BaudRateSettingActivity.class); | |||
| intent.putExtra(Constant.BAUD_RATE, baudRate); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| startActivity(intent); | |||
| break; | |||
| case 1: | |||
| startActivity(new Intent((SensorSettingsActivity.this), ThresholdActivity.class)); | |||
| break; | |||
| case 2: | |||
| intent = new Intent((SensorSettingsActivity.this), ConeSettingActivity.class); | |||
| Log.e(logTag, "sensorId 222: " + sensorId); | |||
| intent.putExtra(Constant.BAUD_RATE, baudRate); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| startActivity(intent); | |||
| break; | |||
| case 3: | |||
| //数据导出 | |||
| confirmExport(); | |||
| break; | |||
| case 4: | |||
| //数据恢复 | |||
| startActivity(new Intent((SensorSettingsActivity.this), DataRecoverActivity.class)); | |||
| break; | |||
| case 5: | |||
| startActivity(new Intent(Settings.ACTION_DATE_SETTINGS)); | |||
| break; | |||
| case 6: | |||
| startActivity(new Intent((SensorSettingsActivity.this), PasswordResetActivity.class)); | |||
| break; | |||
| case 7: | |||
| ToastHelper.showResetSensorDialog((this), new ToastHelper.OnDialogClickListener() { | |||
| @Override | |||
| public void onOKClickListener(View view) { | |||
| reset(); | |||
| } | |||
| @Override | |||
| public void onCancelClickListener(View view) { | |||
| } | |||
| }); | |||
| break; | |||
| case 8: | |||
| if (AccountManager.get().getUserId().equals("root")) { | |||
| startActivity(new Intent((SensorSettingsActivity.this), ThirdSensorSettingsActivity.class)); | |||
| } else { | |||
| Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); | |||
| } | |||
| break; | |||
| case 9: | |||
| if (AccountManager.get().getUserId().equals("root")) { | |||
| intent = new Intent((SensorSettingsActivity.this), ChangeSensorIdSettingsActivity.class); | |||
| intent.putExtra(Constant.BAUD_RATE, baudRate); | |||
| intent.putExtra(Constant.SENSOR_ID, sensorId); | |||
| startActivityForResult(intent, (10001)); | |||
| } else { | |||
| Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); | |||
| } | |||
| break; | |||
| case 10: | |||
| if (AccountManager.get().getUserId().equals("root")) { | |||
| startActivityForResult(new Intent((SensorSettingsActivity.this), ViewOperateLogListActivity.class), 10001); | |||
| } else { | |||
| Toast.makeText((this), "请登录root 后在操作", Toast.LENGTH_SHORT).show(); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| @Override | |||
| protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { | |||
| super.onActivityResult(requestCode, resultCode, data); | |||
| if (requestCode == 10001) { | |||
| if (resultCode == RESULT_OK && data != null) { | |||
| String sensorId = data.getStringExtra(Constant.SENSOR_ID); | |||
| sendSensorId(sensorId); | |||
| } | |||
| } | |||
| } | |||
| private void sendSensorId(String sensorId) { | |||
| StringBuilder sb = new StringBuilder(this.sensorId); | |||
| sb.append("00").append("80").append("04").append(sensorId); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(logTag, "sensor no set: cooked: " + cooked); | |||
| Log.i(logTag, "sensor no set: cooked 2: " + Arrays.toString(cooked.getBytes())); | |||
| mPresenter.write(cooked); | |||
| } | |||
| private void openAssignFolder(final String times) { | |||
| mExportProgressDialog = null; | |||
| new Thread(() -> { | |||
| List<TestRecordsTotal> testRecordsTotals = KJDB.getDefaultInstance().findAllByWhere(TestRecordsTotal.class, "1=1"); | |||
| mExcelMa.write(testRecordsTotals, new PersistHelper.ExportCallback() { | |||
| @Override | |||
| public void exportProgress(int counts, int remain) { | |||
| Log.d(logTag, "exportProgress [counts, remain]:" + counts + " " + remain); | |||
| showExportProgress(counts, remain); | |||
| } | |||
| @Override | |||
| public void finish(int counts, int remain) { | |||
| if (remain != 0) { | |||
| showCancelTip(); | |||
| } | |||
| } | |||
| }, times); | |||
| }).start(); | |||
| } | |||
| //数据导出确认 | |||
| private void confirmExport() { | |||
| runOnUiThread(() -> { | |||
| dismissDialog(null); | |||
| final String items = DateUtils.formatMilliesTimestamp(System.currentTimeMillis(), YYYY_MM_DD_HH_MM); | |||
| final String name = "检测结果(" + items + ").xlsx"; | |||
| String alarm = "导出数据到 内部存储/htjc/sensor/export/" + name + ""; | |||
| AlertDialog a = ToastHelper.showChooseDialogNoShow( | |||
| getString(R.string.import_out_confirm), | |||
| R.mipmap.ic_exclamation_mark, | |||
| alarm, | |||
| getResources().getColor(R.color.button), | |||
| getString(R.string.confirm), getString(R.string.cancel), | |||
| (SensorSettingsActivity.this), | |||
| new ToastHelper.OnDialogClickListener() { | |||
| @Override | |||
| public void onOKClickListener(View view) { | |||
| openAssignFolder(items); | |||
| } | |||
| @Override | |||
| public void onCancelClickListener(View view) { | |||
| } | |||
| }); | |||
| showDialog(a); | |||
| }); | |||
| } | |||
| private void showCancelTip() { | |||
| runOnUiThread(() -> { | |||
| AlertDialog alertDialog = ToastHelper.showTipDialogNoShow((SensorSettingsActivity.this), R.mipmap.chuchang_gray, R.string.cancel); | |||
| showDialog(alertDialog); | |||
| disMissDialogDelay(alertDialog, (3000)); | |||
| }); | |||
| } | |||
| ExportProgressDialog mExportProgressDialog; | |||
| private void showExportProgress(final int count, final int remain) { | |||
| if (mExportProgressDialog == null) { | |||
| runOnUiThread(() -> { | |||
| mExportProgressDialog = new ExportProgressDialog(); | |||
| mExportProgressDialog.showExportDialogNoShow( | |||
| (SensorSettingsActivity.this), | |||
| (View view) -> mExcelMa.stopExport(), | |||
| count, | |||
| remain, | |||
| getString(R.string.importing_to_excel_file), | |||
| getString(R.string.import_out) | |||
| ); | |||
| showDialog(mExportProgressDialog.mAlertDialog); | |||
| }); | |||
| } else { | |||
| mExportProgressDialog.update(this, count, remain); | |||
| } | |||
| } | |||
| //正在设置 | |||
| private void showSettingDialog() { | |||
| runOnUiThread(() -> { | |||
| resetDialog = ToastHelper.showTipDialog((SensorSettingsActivity.this), R.mipmap.ic_setting, R.string.reset_tip); | |||
| disMissDialogDelay(resetDialog, (10000)); | |||
| } | |||
| ); | |||
| } | |||
| private Handler mHandler = new Handler(); | |||
| private Runnable mRunnable; | |||
| @Override | |||
| public void disMissDialogDelay(final AlertDialog alertDialog, int delayMillis) { | |||
| mRunnable = () -> { | |||
| Log.i(logTag, "SensorSettingsActivity, disMissDialogDelay"); | |||
| mPresenter.close(); | |||
| dismissDialogD(alertDialog); | |||
| }; | |||
| mHandler.postDelayed(mRunnable, delayMillis); | |||
| } | |||
| private void reset() { | |||
| showSettingDialog(); | |||
| new Thread(() -> { | |||
| Looper.prepare(); | |||
| new Handler().postDelayed(() -> mPresenter.open(baudRate), (500)); | |||
| Looper.loop(); | |||
| } | |||
| ).start(); | |||
| handler.sendEmptyMessageDelayed(Constant.Command.COMMAND_49, (3000)); | |||
| } | |||
| @SuppressLint("HandlerLeak") | |||
| private Handler handler = new Handler() { | |||
| @Override | |||
| public void handleMessage(Message msg) { | |||
| super.handleMessage(msg); | |||
| if (msg.what == Constant.Command.COMMAND_49) {//恢复出厂值 | |||
| StringBuilder sb = new StringBuilder(sensorId); | |||
| sb.append("00").append("49").append("00"); | |||
| String cooked = "DDDD".concat(sb.toString().concat(CRCUtils.genCrc(sb.toString()))); | |||
| Log.i(logTag, "SensorSettingsActivity, cooked: " + cooked); | |||
| mPresenter.write(cooked); | |||
| } | |||
| } | |||
| }; | |||
| @Override | |||
| public void onSerialOpen(boolean isOpen) { | |||
| } | |||
| @Override | |||
| public void onSerialBaudRate(Integer baudRate) { | |||
| } | |||
| @Override | |||
| public void onSerialData(RawData rawData) { | |||
| if (rawData.getItemType() == RawData.TYPE_RECEIVE) { | |||
| Log.i(logTag, "SensorSettingsActivity, onSerialData: " + rawData.getMessage()); | |||
| byte[] bytes = ByteUtils.hexStrToBytes(rawData.getMessage()); | |||
| Log.i(logTag, "SensorSettingsActivity, onSerialData 2: " + Arrays.toString(bytes)); | |||
| if (bytes.length > 8) { | |||
| if ((bytes[6] & 0xff) == 0 && (bytes[7] & 0xff) == Constant.Command.COMMAND_4A) { | |||
| Log.i(logTag, "SensorSettingsActivity, onSerialData, 0x49 feedback: " + rawData.getMessage()); | |||
| mPresenter.close(); | |||
| dismissDialog(resetDialog); | |||
| mHandler.removeCallbacks(mRunnable); | |||
| restoreToFactorySuccess(); | |||
| } else { | |||
| mPresenter.close(); | |||
| dismissDialog(resetDialog); | |||
| mHandler.removeCallbacks(mRunnable); | |||
| restoreToFactoryFail(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public void onSerialError(Integer errorCode) { | |||
| } | |||
| //设置成功 | |||
| private void restoreToFactorySuccess() { | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(resetDialog); | |||
| ToastHelper.showSubmitDialog( | |||
| getString(R.string.restore_factory_success), | |||
| R.mipmap.img_right, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.blue_button_bg), | |||
| getString(R.string.btn_ensure), | |||
| (SensorSettingsActivity.this), | |||
| (View view) -> finish() | |||
| ); | |||
| }); | |||
| } | |||
| //设置失败 | |||
| private void restoreToFactoryFail() { | |||
| runOnUiThread(() -> { | |||
| disMissLoadingDialog(resetDialog); | |||
| ToastHelper.showSubmitDialog( | |||
| getString(R.string.restore_factory_failed), | |||
| R.mipmap.img_cross, | |||
| getString(R.string.go_back_init_screen_content), | |||
| getResources().getColor(R.color.button), | |||
| getString(R.string.btn_ensure), | |||
| (SensorSettingsActivity.this), | |||
| (View view) -> { | |||
| } | |||
| ); | |||
| } | |||
| ); | |||
| } | |||
| } | |||
| @ -0,0 +1,40 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import com.handset.serialportsensor.R; | |||
| import io.reactivex.Observable; | |||
| import io.reactivex.disposables.Disposable; | |||
| import java.util.concurrent.TimeUnit; | |||
| public class SplashActivity extends AppCompatActivity { | |||
| private Disposable mDisposable; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_splash); | |||
| mDisposable = Observable | |||
| .timer((1), TimeUnit.SECONDS) | |||
| .subscribe(this::jumpToMain, Throwable::printStackTrace); | |||
| } | |||
| @SuppressWarnings(value = "unused") | |||
| private void jumpToMain(Long aLong) { | |||
| startActivity(new Intent((this), Main2Activity.class)); | |||
| finish(); | |||
| } | |||
| @Override | |||
| protected void onDestroy() { | |||
| super.onDestroy(); | |||
| if (mDisposable != null) { | |||
| mDisposable.dispose(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,41 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.view.View; | |||
| import android.widget.CompoundButton; | |||
| import android.widget.ImageView; | |||
| import android.widget.Switch; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.utils.SPUtils; | |||
| /** | |||
| * Created by zy on 2019/2/23. | |||
| */ | |||
| public class ThirdSensorSettingsActivity extends AppCompatActivity { | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_third_sensor_settings); | |||
| Switch sw_sensor = (Switch) findViewById(R.id.sw_sensor); | |||
| boolean sensor_third_enable = SPUtils.getInstance(this).get("sensor_third_enable", false); | |||
| sw_sensor.setChecked(sensor_third_enable); | |||
| sw_sensor.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { | |||
| @Override | |||
| public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { | |||
| SPUtils.getInstance(ThirdSensorSettingsActivity.this).put("sensor_third_enable", isChecked); | |||
| AccountManager.get().putUserData("sensor_third_enable", isChecked + ""); | |||
| } | |||
| }); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText("第三方传感器弹筒信息开关"); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View v) -> ThirdSensorSettingsActivity.this.finish()); | |||
| } | |||
| } | |||
| @ -0,0 +1,264 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.content.Context; | |||
| import android.os.Bundle; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.text.TextUtils; | |||
| import android.view.MotionEvent; | |||
| import android.view.View; | |||
| import android.view.inputmethod.InputMethodManager; | |||
| import android.widget.EditText; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.google.gson.Gson; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.account.AccountManager; | |||
| import com.handset.serialportsensor.bean.ThresholdBean; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import com.handset.serialportsensor.utils.SpUtil; | |||
| public class ThresholdActivity extends AppCompatActivity { | |||
| private EditText etTempLow; | |||
| private EditText etTempHigh; | |||
| private EditText etHumLow; | |||
| private EditText etHumHigh; | |||
| private EditText etPressureLow1; | |||
| private EditText etPressureHigh1; | |||
| private EditText etPressureLow2; | |||
| private EditText etPressureHigh2; | |||
| private EditText etDiffPressureLow; | |||
| private EditText etDiffPressureHigh; | |||
| @Override | |||
| protected void onCreate(Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_threshold); | |||
| initView(); | |||
| setDefaultValue(); | |||
| } | |||
| @Override | |||
| public boolean onTouchEvent(MotionEvent event) { | |||
| InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); | |||
| if(im != null) { | |||
| View view = getCurrentFocus(); | |||
| if(view != null) { | |||
| im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); | |||
| } | |||
| } | |||
| return super.onTouchEvent(event); | |||
| } | |||
| private void initView() { | |||
| initTitle(); | |||
| } | |||
| private void initTitle() { | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener((View view) -> finish()); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| tvTitle.setText(R.string.set_threshold_title); | |||
| etTempLow = findViewById(R.id.et_temp_low); | |||
| etTempHigh = findViewById(R.id.et_temp_high); | |||
| etHumLow = findViewById(R.id.et_humidity_low); | |||
| etHumHigh = findViewById(R.id.et_humidity_high); | |||
| etPressureLow1 = findViewById(R.id.et_pressure1_low); | |||
| etPressureHigh1 = findViewById(R.id.et_pressure1_high); | |||
| etPressureLow2 = findViewById(R.id.et_pressure2_low); | |||
| etPressureHigh2 = findViewById(R.id.et_pressure2_high); | |||
| etDiffPressureHigh = findViewById(R.id.et_pressure_yahcha_high); | |||
| etDiffPressureLow = findViewById(R.id.et_pressure_yacha_low); | |||
| findViewById(R.id.btn_save).setOnClickListener((View view) -> save()); | |||
| } | |||
| private void save() { | |||
| if (check()) { | |||
| ThresholdBean bean = new ThresholdBean(); | |||
| bean.setTemperatureFloor(etTempLow.getText().toString()); | |||
| bean.setTemperatureCeiling(etTempHigh.getText().toString()); | |||
| bean.setHumidityFloor(etHumLow.getText().toString()); | |||
| bean.setHumidityCeiling(etHumHigh.getText().toString()); | |||
| bean.setInnerPressureFloor(etPressureLow1.getText().toString()); | |||
| bean.setInnerPressureCeiling(etPressureHigh1.getText().toString()); | |||
| bean.setOuterPressureFloor(etPressureLow2.getText().toString()); | |||
| bean.setOuterPressureCeiling(etPressureHigh2.getText().toString()); | |||
| bean.setDiffPressureFloor(etDiffPressureLow.getText().toString()); | |||
| bean.setDiffPressureCeiling(etDiffPressureHigh.getText().toString()); | |||
| SpUtil.put(this, Constant.THRESHOLD_KEY, new Gson().toJson(bean)); | |||
| Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show(); | |||
| AccountManager.get().putUserData("ThresholdBean", "ThresholdBean"); | |||
| finish(); | |||
| } | |||
| } | |||
| private boolean check() { | |||
| if (!checkDataFormat(etTempLow.getText().toString())) { | |||
| Toast.makeText(this, "温度下限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etTempHigh.getText().toString())) { | |||
| Toast.makeText(this, "温度上限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etHumLow.getText().toString())) { | |||
| Toast.makeText(this, "湿度下限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etHumHigh.getText().toString())) { | |||
| Toast.makeText(this, "湿度上限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etPressureLow1.getText().toString())) { | |||
| Toast.makeText(this, "内压下限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etPressureHigh1.getText().toString())) { | |||
| Toast.makeText(this, "内压上限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etPressureLow2.getText().toString())) { | |||
| Toast.makeText(this, "外压下限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etPressureHigh2.getText().toString())) { | |||
| Toast.makeText(this, "外压上限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etDiffPressureLow.getText().toString())) { | |||
| Toast.makeText(this, "压差下限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } else if (!checkDataFormat(etDiffPressureHigh.getText().toString())) { | |||
| Toast.makeText(this, "压差上限格式不正确", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!between(checkDataFormatF(etTempHigh.getText().toString()), 85f, -45f) | |||
| || !between(checkDataFormatF(etTempLow.getText().toString()), 85f, -45f)) { | |||
| Toast.makeText(this, "温度范围只能输入 -45~85", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!between(checkDataFormatF(etHumHigh.getText().toString()), 100f, 0f) | |||
| || !between(checkDataFormatF(etHumLow.getText().toString()), 100f, 0f)) { | |||
| Toast.makeText(this, "湿度范围只能输入 0~100", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!between(checkDataFormatF(etPressureHigh1.getText().toString()), 200f, 0f) | |||
| || !between(checkDataFormatF(etPressureLow1.getText().toString()), 200f, 0f) | |||
| || !between(checkDataFormatF(etPressureHigh2.getText().toString()), 200f, 0f) | |||
| || !between(checkDataFormatF(etPressureLow2.getText().toString()), 200f, 0f)) { | |||
| Toast.makeText(this, "压力范围只能输入 0~200", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!between(checkDataFormatF(etDiffPressureHigh.getText().toString()), 30f, -20f) | |||
| || !between(checkDataFormatF(etDiffPressureLow.getText().toString()), 30f, -20f)) { | |||
| Toast.makeText(this, "压差范围只能输入 -20~30", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!compareBS(etTempHigh.getText().toString(), etTempLow.getText().toString())) { | |||
| Toast.makeText(this, "湿度上限不能低于下限", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!compareBS(etHumHigh.getText().toString(), etHumLow.getText().toString())) { | |||
| Toast.makeText(this, "湿度上限不能低于下限", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!compareBS(etPressureHigh1.getText().toString(), etPressureLow1.getText().toString())) { | |||
| Toast.makeText(this, "内压上限不能低于下限", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!compareBS(etPressureHigh2.getText().toString(), etPressureLow2.getText().toString())) { | |||
| Toast.makeText(this, "外压上限不能低于下限", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| if (!compareBS(etDiffPressureHigh.getText().toString(), etDiffPressureLow.getText().toString())) { | |||
| Toast.makeText(this, "压差上限不能低于下限", Toast.LENGTH_SHORT).show(); | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| private boolean between(Float f, Float up, Float low) { | |||
| if (f == null || up == null || low == null) { | |||
| return false; | |||
| } | |||
| return low <= f && f <= up; | |||
| } | |||
| private boolean checkDataFormat(String a) { | |||
| return checkDataFormatF(a) != null; | |||
| } | |||
| private Float checkDataFormatF(String a) { | |||
| if (TextUtils.isEmpty(a)) { | |||
| return null; | |||
| } | |||
| try { | |||
| Float f = Float.parseFloat(a); | |||
| return f; | |||
| } catch (NumberFormatException e) { | |||
| e.printStackTrace(); | |||
| return null; | |||
| } | |||
| } | |||
| private boolean compareBS(String bigger, String smaller) { | |||
| if (TextUtils.isEmpty(bigger) || TextUtils.isEmpty(smaller)) { | |||
| return false; | |||
| } | |||
| try { | |||
| Float bigErf = Float.parseFloat(bigger); | |||
| Float smallErf = Float.parseFloat(smaller); | |||
| if (bigErf >= smallErf) { | |||
| return true; | |||
| } | |||
| } catch (NumberFormatException e) { | |||
| e.printStackTrace(); | |||
| return false; | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * 配置默认阈值参数 | |||
| */ | |||
| private void setDefaultValue() { | |||
| ThresholdBean bean = new ThresholdBean(); | |||
| bean.setTemperatureFloor("-40"); | |||
| bean.setTemperatureCeiling("65"); | |||
| bean.setHumidityFloor("0"); | |||
| bean.setHumidityCeiling("100"); | |||
| bean.setInnerPressureFloor("80"); | |||
| bean.setInnerPressureCeiling("150"); | |||
| bean.setOuterPressureFloor("80"); | |||
| bean.setOuterPressureCeiling("150"); | |||
| bean.setDiffPressureFloor("-20"); | |||
| bean.setDiffPressureCeiling("30"); | |||
| String bean2 = (String) SpUtil.get(this, Constant.THRESHOLD_KEY, ""); | |||
| ThresholdBean bean1 = null; | |||
| if (!TextUtils.isEmpty(bean2)) { | |||
| bean1 = new Gson().fromJson(bean2, ThresholdBean.class); | |||
| } | |||
| if (bean1 != null) { | |||
| bean = bean1; | |||
| } | |||
| etTempLow.setText(bean.getTemperatureFloor()); | |||
| etTempHigh.setText(bean.getTemperatureCeiling()); | |||
| etHumLow.setText(bean.getHumidityFloor()); | |||
| etHumHigh.setText(bean.getHumidityCeiling()); | |||
| etPressureLow1.setText(bean.getInnerPressureFloor()); | |||
| etPressureHigh1.setText(bean.getInnerPressureCeiling()); | |||
| etPressureLow2.setText(bean.getOuterPressureFloor()); | |||
| etPressureHigh2.setText(bean.getOuterPressureCeiling()); | |||
| etDiffPressureHigh.setText(bean.getDiffPressureCeiling()); | |||
| etDiffPressureLow.setText(bean.getDiffPressureFloor()); | |||
| } | |||
| } | |||
| @ -0,0 +1,70 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.text.TextUtils; | |||
| import android.view.View; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.IOException; | |||
| /** | |||
| * Created by zy on 2019/2/28. | |||
| */ | |||
| public class ViewLogActivity extends AppCompatActivity { | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_view_log); | |||
| Intent intent = getIntent(); | |||
| String filePath = intent.getStringExtra("file_path"); | |||
| TextView tv_log = findViewById(R.id.tv_log); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText("操作日志"); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener(new View.OnClickListener() { | |||
| @Override | |||
| public void onClick(View v) { | |||
| ViewLogActivity.this.finish(); | |||
| } | |||
| }); | |||
| if (!TextUtils.isEmpty(filePath)) { | |||
| String ac = getfileC(filePath); | |||
| tv_log.setText(ac); | |||
| } | |||
| } | |||
| private String getfileC(String filePath) { | |||
| String c = ""; | |||
| File file = new File(filePath); | |||
| FileInputStream in; | |||
| try { | |||
| in = new FileInputStream(file); | |||
| int l = (int) file.length(); | |||
| byte[] filecontent = new byte[l]; | |||
| in.read(filecontent); | |||
| in.close(); | |||
| c = new String(filecontent); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return c; | |||
| } | |||
| } | |||
| @ -0,0 +1,136 @@ | |||
| package com.handset.serialportsensor.activity; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.os.Bundle; | |||
| import android.support.annotation.NonNull; | |||
| import android.support.annotation.Nullable; | |||
| import android.support.constraint.ConstraintLayout; | |||
| import android.support.v7.app.AppCompatActivity; | |||
| import android.support.v7.widget.DefaultItemAnimator; | |||
| import android.support.v7.widget.DividerItemDecoration; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.view.ViewGroup; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.utils.Slog; | |||
| import com.handset.serialportsensor.view.LinearLayoutManagerCus; | |||
| import java.io.File; | |||
| import java.util.List; | |||
| import static android.support.v7.widget.DividerItemDecoration.VERTICAL; | |||
| /** | |||
| * Created by zy on 2019/2/27. | |||
| */ | |||
| public class ViewOperateLogListActivity extends AppCompatActivity { | |||
| RecyclerView mRecyclerView; | |||
| MyAdapter myAdapter; | |||
| @Override | |||
| protected void onCreate(@Nullable Bundle savedInstanceState) { | |||
| super.onCreate(savedInstanceState); | |||
| setContentView(R.layout.activity_view_operate_log); | |||
| mRecyclerView = findViewById(R.id.recycle_view); | |||
| mRecyclerView.setLayoutManager(new LinearLayoutManagerCus(this)); | |||
| DefaultItemAnimator animator = new DefaultItemAnimator(); | |||
| animator.setRemoveDuration(1000); | |||
| mRecyclerView.setItemAnimator(animator); | |||
| TextView tvTitle = findViewById(R.id.title_text); | |||
| ImageView ivBack = findViewById(R.id.title_back); | |||
| tvTitle.setText("操作日志"); | |||
| ivBack.setVisibility(View.VISIBLE); | |||
| ivBack.setOnClickListener(new View.OnClickListener() { | |||
| @Override | |||
| public void onClick(View v) { | |||
| ViewOperateLogListActivity.this.finish(); | |||
| } | |||
| }); | |||
| mRecyclerView.addItemDecoration(new DividerItemDecoration(this, VERTICAL)); | |||
| getOperateLog(); | |||
| } | |||
| private void getOperateLog() { | |||
| List<File> list = Slog.getOperateLogFiles(); | |||
| //设置适配器 | |||
| if (myAdapter == null) { | |||
| myAdapter = new MyAdapter(this, list); | |||
| mRecyclerView.setAdapter(myAdapter); | |||
| } else { | |||
| myAdapter.setDataList(list); | |||
| } | |||
| } | |||
| static class ViewHolder extends RecyclerView.ViewHolder { | |||
| TextView tvIndex; | |||
| TextView tvLog; | |||
| ConstraintLayout cl_content; | |||
| public ViewHolder(@NonNull View itemView) { | |||
| super(itemView); | |||
| tvIndex = itemView.findViewById(R.id.tv_item_index); | |||
| tvLog = itemView.findViewById(R.id.tv_name); | |||
| cl_content = itemView.findViewById(R.id.cl_content); | |||
| } | |||
| } | |||
| static class MyAdapter extends RecyclerView.Adapter<ViewHolder> { | |||
| List<File> mDataList; | |||
| private OnItemClickListener mOnItemClickListener; | |||
| Context mContext; | |||
| public MyAdapter(Context context, List<File> mList) { | |||
| mContext = context; | |||
| this.mDataList = mList; | |||
| } | |||
| @NonNull | |||
| @Override | |||
| public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { | |||
| return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.operate_log_item, null, false)); | |||
| } | |||
| @Override | |||
| public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { | |||
| final File file = mDataList.get(i); | |||
| viewHolder.tvIndex.setText((i + 1) + ""); | |||
| viewHolder.tvLog.setText(file.getName()); | |||
| viewHolder.cl_content.setOnClickListener(new View.OnClickListener() { | |||
| @Override | |||
| public void onClick(View v) { | |||
| Intent intent = new Intent(mContext, ViewLogActivity.class); | |||
| intent.putExtra("file_path", file.getAbsolutePath()); | |||
| mContext.startActivity(intent); | |||
| } | |||
| }); | |||
| } | |||
| @Override | |||
| public int getItemCount() { | |||
| return mDataList.size(); | |||
| } | |||
| public void setOnItemClickListener(OnItemClickListener onItemClickListener) { | |||
| this.mOnItemClickListener = onItemClickListener; | |||
| } | |||
| public void setDataList(List<File> dataList) { | |||
| mDataList = dataList; | |||
| notifyDataSetChanged(); | |||
| } | |||
| } | |||
| public interface OnItemClickListener { | |||
| void onItemClick(View view, int position); | |||
| } | |||
| } | |||
| @ -0,0 +1,19 @@ | |||
| package com.handset.serialportsensor.adapter; | |||
| import android.support.annotation.Nullable; | |||
| import com.chad.library.adapter.base.BaseQuickAdapter; | |||
| import com.chad.library.adapter.base.BaseViewHolder; | |||
| import com.handset.serialportsensor.R; | |||
| import java.util.List; | |||
| public class HistoryAdapter extends BaseQuickAdapter<String,BaseViewHolder> { | |||
| public HistoryAdapter(@Nullable List<String> data) { | |||
| super(R.layout.rv_item_history, data); | |||
| } | |||
| @Override | |||
| protected void convert(BaseViewHolder helper, String item) { | |||
| helper.setText(R.id.item_history, item); | |||
| } | |||
| } | |||
| @ -0,0 +1,86 @@ | |||
| package com.handset.serialportsensor.adapter; | |||
| import android.text.TextUtils; | |||
| import com.blankj.utilcode.util.SPUtils; | |||
| import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; | |||
| import com.chad.library.adapter.base.BaseViewHolder; | |||
| import com.chad.library.adapter.base.entity.MultiItemEntity; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.LeftDetailBean; | |||
| import com.handset.serialportsensor.bean.LeftHeadBean; | |||
| import java.util.List; | |||
| public class LeftAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> { | |||
| public static final int TYPE_HEAD = 1; | |||
| public static final int TYPE_DETAIL = 2; | |||
| /** | |||
| * Same as QuickAdapter#QuickAdapter(Context,int) but with | |||
| * some initialization data. | |||
| * | |||
| * @param data A new list is created out of this one to avoid mutable list | |||
| */ | |||
| public LeftAdapter(List<MultiItemEntity> data) { | |||
| super(data); | |||
| addItemType(TYPE_HEAD, R.layout.left_rv_item_head); | |||
| addItemType(TYPE_DETAIL, R.layout.left_rv_item_detail); | |||
| } | |||
| @Override | |||
| protected void convert(BaseViewHolder helper, MultiItemEntity item) { | |||
| switch (helper.getItemViewType()) { | |||
| case TYPE_HEAD: | |||
| if (item instanceof LeftHeadBean) { | |||
| helper.setImageResource(R.id.left_rv_item_image, ((LeftHeadBean) item).getImageRes()) | |||
| .setText(R.id.left_rv_item_title, ((LeftHeadBean) item).getTitle()) | |||
| .setText(R.id.left_rv_item_value, | |||
| TextUtils.isEmpty(((LeftHeadBean) item).getValue()) ? "" | |||
| : ((LeftHeadBean) item).getValue()); | |||
| helper.itemView.setOnClickListener(v -> { | |||
| collapseOrExpand(item); | |||
| }); | |||
| } | |||
| break; | |||
| case TYPE_DETAIL: | |||
| if (item instanceof LeftDetailBean) { | |||
| helper.setText(R.id.left_rv_item_item, ((LeftDetailBean) item).getItem()) | |||
| .setChecked(R.id.left_rv_item_check, ((LeftDetailBean) item).isCheck()); | |||
| helper.itemView.setOnClickListener(v -> { | |||
| int parentPosition = getParentPosition(item); | |||
| LeftHeadBean headBean = (LeftHeadBean) getData().get(parentPosition); | |||
| List<LeftDetailBean> subItems = headBean.getSubItems(); | |||
| for (int i = 0; i < subItems.size(); i++) { | |||
| if (subItems.get(i).isCheck()) { | |||
| subItems.get(i).setCheck(false); | |||
| break; | |||
| } | |||
| } | |||
| int subPosition = helper.getAdapterPosition() - parentPosition - 1; | |||
| LeftDetailBean bean = subItems.get(subPosition); | |||
| bean.setCheck(true); | |||
| headBean.setValue(String.valueOf(bean.getItem())); | |||
| SPUtils.getInstance().put(headBean.getSpKey(), headBean.getValue()); | |||
| notifyDataSetChanged(); | |||
| }); | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| public void collapseOrExpand(MultiItemEntity item) { | |||
| int position = getParentPosition(item); | |||
| if (((LeftHeadBean) item).isExpanded()) { | |||
| collapse(position); | |||
| } else { | |||
| expand(position); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,46 @@ | |||
| package com.handset.serialportsensor.adapter; | |||
| import android.text.TextUtils; | |||
| import com.chad.library.adapter.base.BaseMultiItemQuickAdapter; | |||
| import com.chad.library.adapter.base.BaseViewHolder; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import java.util.List; | |||
| import java.util.Locale; | |||
| public class MsgAdapter extends BaseMultiItemQuickAdapter<RawData, BaseViewHolder> { | |||
| private String mFormat; | |||
| /** | |||
| * Same as QuickAdapter#QuickAdapter(Context,int) but with | |||
| * some initialization data. | |||
| * | |||
| * @param data A new list is created out of this one to avoid mutable list | |||
| */ | |||
| public MsgAdapter(List<RawData> data) { | |||
| super(data); | |||
| addItemType(RawData.TYPE_RECEIVE, R.layout.rv_item_receive); | |||
| addItemType(RawData.TYPE_SEND, R.layout.rv_item_send); | |||
| } | |||
| @Override | |||
| protected void convert(BaseViewHolder helper, RawData item) { | |||
| if (TextUtils.isEmpty(mFormat)) { | |||
| mFormat = mContext.getString(R.string.time_format); | |||
| } | |||
| if (item.getItemType() == RawData.TYPE_RECEIVE) { | |||
| helper.setGone(R.id.item_receive_date, !TextUtils.isEmpty(item.getDate())) | |||
| .setText(R.id.item_receive_date, TextUtils.isEmpty(item.getDate()) ? "" | |||
| : String.format(Locale.getDefault(), mFormat, item.getDate())) | |||
| .setText(R.id.item_receive_contain, item.getMessage()); | |||
| } else { | |||
| helper.setGone(R.id.item_send_date, !TextUtils.isEmpty(item.getDate())) | |||
| .setText(R.id.item_send_date, TextUtils.isEmpty(item.getDate()) ? "" | |||
| : String.format(Locale.getDefault(), mFormat, item.getDate())) | |||
| .setText(R.id.item_send_contain, item.getMessage()); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,98 @@ | |||
| package com.handset.serialportsensor.adapter; | |||
| import android.support.annotation.NonNull; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.view.ViewGroup; | |||
| import android.widget.ImageView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.TextView; | |||
| import android.widget.Toast; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.bean.SettingsItem; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import java.util.List; | |||
| public class SettingsAdapter extends RecyclerView.Adapter<SettingsAdapter.ViewHolder> { | |||
| private List<SettingsItem> list; | |||
| private int role; | |||
| private OnItemClickListener listener; | |||
| public void setOnItemClickListener(OnItemClickListener onItemClickListener) { | |||
| this.listener = onItemClickListener; | |||
| } | |||
| public interface OnItemClickListener { | |||
| void onItemClick(View view, int position); | |||
| } | |||
| public SettingsAdapter(List<SettingsItem> list, int role) { | |||
| this.list = list; | |||
| this.role = role; | |||
| } | |||
| @NonNull | |||
| @Override | |||
| public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { | |||
| View inflate = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.settings_adapter_item, viewGroup, false); | |||
| return new ViewHolder(inflate); | |||
| } | |||
| @Override | |||
| public void onBindViewHolder(@NonNull ViewHolder viewHolder, final int i) { | |||
| final SettingsItem item = list.get(i); | |||
| viewHolder.iv_img.setImageResource(item.getIconRes()); | |||
| viewHolder.tv_title.setText(item.getName()); | |||
| viewHolder.itemView.setOnClickListener((View view) -> | |||
| Toast.makeText(view.getContext(), item.getName(), Toast.LENGTH_SHORT).show() | |||
| ); | |||
| if (i == list.size() - 1) { | |||
| viewHolder.line.setVisibility(View.GONE); | |||
| if (role == Constant.SENIOR_ROLE) { | |||
| viewHolder.third_layout.setVisibility(View.VISIBLE); | |||
| } else { | |||
| viewHolder.third_layout.setVisibility(View.INVISIBLE); | |||
| } | |||
| } else { | |||
| viewHolder.third_layout.setVisibility(View.GONE); | |||
| viewHolder.line.setVisibility(View.VISIBLE); | |||
| } | |||
| viewHolder.itemView.setOnClickListener((View view) -> listener.onItemClick(view, i)); | |||
| if (role == Constant.NOT_CONNECTED_ROLE) { | |||
| if (item.getPosition() == 0 || item.getPosition() == 2 || item.getPosition() == 7 || item.getPosition() == 9) { | |||
| viewHolder.iv_img.setImageResource(R.mipmap.ic_settings3_gray); | |||
| viewHolder.tv_title.setTextColor(viewHolder.tv_title.getContext().getResources().getColor(R.color.very_light_gray)); | |||
| viewHolder.iv_right.setImageResource(R.mipmap.ic_right_arrow_light); | |||
| viewHolder.itemView.setClickable(false); | |||
| } | |||
| } | |||
| } | |||
| @Override | |||
| public int getItemCount() { | |||
| return list.size(); | |||
| } | |||
| class ViewHolder extends RecyclerView.ViewHolder { | |||
| private ImageView iv_img; | |||
| private TextView tv_title; | |||
| private ImageView iv_right; | |||
| private View line; | |||
| private LinearLayout third_layout; | |||
| public ViewHolder(@NonNull View itemView) { | |||
| super(itemView); | |||
| iv_img = itemView.findViewById(R.id.iv_img); | |||
| tv_title = itemView.findViewById(R.id.tv_title); | |||
| iv_right = itemView.findViewById(R.id.iv_right); | |||
| line = itemView.findViewById(R.id.line); | |||
| third_layout = itemView.findViewById(R.id.third_layout); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,31 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import com.chad.library.adapter.base.entity.MultiItemEntity; | |||
| import com.handset.serialportsensor.adapter.LeftAdapter; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @Builder | |||
| @NoArgsConstructor | |||
| public class LeftDetailBean implements MultiItemEntity { | |||
| private String item; | |||
| private boolean isCheck; | |||
| public LeftDetailBean(String item) { | |||
| this.item = item; | |||
| } | |||
| public LeftDetailBean(String item, boolean isCheck) { | |||
| this.item = item; | |||
| this.isCheck = isCheck; | |||
| } | |||
| @Override | |||
| public int getItemType() { | |||
| return LeftAdapter.TYPE_DETAIL; | |||
| } | |||
| } | |||
| @ -0,0 +1,36 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import android.support.annotation.DrawableRes; | |||
| import com.chad.library.adapter.base.entity.AbstractExpandableItem; | |||
| import com.chad.library.adapter.base.entity.MultiItemEntity; | |||
| import com.handset.serialportsensor.adapter.LeftAdapter; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.EqualsAndHashCode; | |||
| import lombok.NoArgsConstructor; | |||
| @EqualsAndHashCode(callSuper = true) | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| public class LeftHeadBean extends AbstractExpandableItem<LeftDetailBean> implements MultiItemEntity { | |||
| @DrawableRes | |||
| private int imageRes; | |||
| private String title; | |||
| private String value; | |||
| private String spKey; | |||
| @Override | |||
| public int getLevel() { | |||
| return 0; | |||
| } | |||
| @Override | |||
| public int getItemType() { | |||
| return LeftAdapter.TYPE_HEAD; | |||
| } | |||
| } | |||
| @ -0,0 +1,187 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import android.util.Log; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| import java.math.BigDecimal; | |||
| import java.math.RoundingMode; | |||
| import java.text.DecimalFormat; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @Builder | |||
| @NoArgsConstructor | |||
| @AllArgsConstructor | |||
| public class MetaData { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private static final BigDecimal T_CEILING = new BigDecimal(100.00f); | |||
| private static final BigDecimal T_FLOOR = new BigDecimal(-60.00f); | |||
| private static final BigDecimal H_CEILING = new BigDecimal(100.00f); | |||
| private static final BigDecimal H_FLOOR = new BigDecimal(00.00f); | |||
| private static final BigDecimal I_CEILING = new BigDecimal(300.00f); | |||
| private static final BigDecimal I_FLOOR = new BigDecimal(00.00f); | |||
| private static final BigDecimal O_CEILING = new BigDecimal(300.00f); | |||
| private static final BigDecimal O_FLOOR = new BigDecimal(00.00f); | |||
| private static final BigDecimal DP_CEILING = new BigDecimal(600.00f); | |||
| private static final BigDecimal DP_FLOOR = new BigDecimal(-600.00f); | |||
| private static final BigDecimal P20_CEILING = new BigDecimal(300.00f); | |||
| private static final BigDecimal P20_FLOOR = new BigDecimal(00.00f); | |||
| private static final BigDecimal H20_CEILING = new BigDecimal(100.00f); | |||
| private static final BigDecimal H20_FLOOR = new BigDecimal(00.00f); | |||
| private static final int[] temperatureConvertDatum = { | |||
| 18, 23, 28, 34, 41, 50, 61, 73, 88, 105, | |||
| 125, 148, 175, 207, 244, 286, 334, 390, 454, 528, | |||
| 611, 706, 814, 935, 1073, 1228, 1403, 1599, 1819, 2065, | |||
| 2339, 2645, 2985, 3362, 3781, 4244, 4756, 5321, 5942, 6626, | |||
| 7377, 8201, 9103, 10089, 11165, 12339, 13618, 15009, 16520, 18160, 19937 | |||
| }; | |||
| private Integer makerId; | |||
| private String sensorNo; | |||
| private String sensorNoRadix; | |||
| private String eggNo; | |||
| private String eggType; | |||
| private String coneNo; | |||
| private String coneUsedTimes; | |||
| private Float temperature; | |||
| private Float humidity; | |||
| private Float innerPressure; | |||
| private Float outerPressure; | |||
| private Float diffPressure; | |||
| private Float degree20Pressure; | |||
| private Float degree20Humidity; | |||
| public void doCalcMeta(String data) { | |||
| byte[] bytes = ByteUtils.hexStrToBytes(data.substring(0, data.length() - 4)); | |||
| switch (bytes[7] & 0xff) { | |||
| case Constant.Command.COMMAND_29: | |||
| this.setTemperature((float) parseValue(bytes) / 100); | |||
| break; | |||
| case Constant.Command.COMMAND_2A: | |||
| this.setInnerPressure((float) parseValue(bytes) / 1000); | |||
| break; | |||
| case Constant.Command.COMMAND_2B: | |||
| this.setHumidity((float) parseValue(bytes) / 100); | |||
| break; | |||
| case Constant.Command.COMMAND_2C: | |||
| this.setOuterPressure((float) parseValue(bytes) / 1000); | |||
| break; | |||
| case Constant.Command.COMMAND_2D: | |||
| this.setDiffPressure((float) parseValue(bytes) / 1000); | |||
| break; | |||
| case Constant.Command.COMMAND_2E: | |||
| this.setDegree20Humidity((float) parseValue(bytes) / 100); | |||
| break; | |||
| case Constant.Command.COMMAND_2F: | |||
| this.setDegree20Pressure((float) parseValue(bytes) / 1000); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| public void doCalcMetaEx() { | |||
| calcPressDiff(); | |||
| calcPressOfDegree20(); | |||
| calcHumidityOfDegree20(); | |||
| } | |||
| public void calcPressDiff() { | |||
| try { | |||
| if(this.diffPressure == 0) { | |||
| Log.i(logTag, "Diff pressure not report, need to be calculated"); | |||
| this.diffPressure = this.innerPressure - this.outerPressure; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| this.diffPressure = 0.00f; | |||
| } | |||
| } | |||
| public void calcPressOfDegree20() { | |||
| try { | |||
| if(this.degree20Pressure == 0) { | |||
| Log.i(logTag, "20 degree pressure not report, need to be calculated"); | |||
| int tempMustInt = (int) (this.temperature * 10); | |||
| double temp = (293000.00) / ((tempMustInt + 400) + 2330); | |||
| double innerPress20Degree = (temp * (this.innerPressure * 1000)) / 100 / 1000; | |||
| DecimalFormat df = new DecimalFormat(Constant.FORMAT_FLOAT_PATTERN); | |||
| df.setRoundingMode(RoundingMode.FLOOR); | |||
| this.degree20Pressure = Float.valueOf(df.format(innerPress20Degree)); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| this.degree20Pressure = 0.00f; | |||
| } | |||
| } | |||
| public void calcHumidityOfDegree20() { | |||
| try { | |||
| if(this.degree20Humidity == 0) { | |||
| Log.i(logTag, "20 degree humidity not report, need to be calculated"); | |||
| int tmp = (((int) (this.temperature * 10) + 400) / 10) / 2; | |||
| tmp = (((int) (this.temperature * 10) + 400) / 10) % 2 == 0 ? tmp : tmp + 1; | |||
| tmp = tmp > 50 || tmp < 0 ? 50 : tmp; | |||
| double degree20Humidity = (temperatureConvertDatum[tmp] * ((double) (this.humidity * 100) / 100)) / 2339; | |||
| DecimalFormat df2 = new DecimalFormat(Constant.FORMAT_FLOAT_PATTERN); | |||
| df2.setRoundingMode(RoundingMode.FLOOR); | |||
| this.degree20Humidity = Float.valueOf(df2.format(degree20Humidity)); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| this.degree20Humidity = 0.00f; | |||
| } | |||
| this.degree20Humidity = new BigDecimal(this.degree20Humidity).compareTo(H20_CEILING) >=0 ? 100.f : this.degree20Humidity; | |||
| } | |||
| private int parseValue(byte[] bytes) { | |||
| return (bytes[9] & 0xff) | ((bytes[10] & 0xff) << 8) | ((bytes[11] & 0xff) << 16) | ((bytes[12] & 0xff) << 24); | |||
| } | |||
| public boolean isValid() { | |||
| BigDecimal t = new BigDecimal(this.temperature); | |||
| BigDecimal h = new BigDecimal(this.humidity); | |||
| BigDecimal i = new BigDecimal(this.innerPressure); | |||
| BigDecimal o = new BigDecimal(this.outerPressure); | |||
| BigDecimal dp = new BigDecimal(this.diffPressure); | |||
| BigDecimal p20 = new BigDecimal(this.degree20Pressure); | |||
| BigDecimal h20 = new BigDecimal(this.degree20Humidity); | |||
| Log.i(logTag, "t:" + t.floatValue() + ",h:" + h.floatValue() + ",i:" + i.floatValue() + ",o:" + o.floatValue() + ",dp:" + dp.floatValue() + ",p20:" + p20.floatValue()+ ",h20:" + h20.floatValue()); | |||
| return t.compareTo(T_CEILING) <= 0 && t.compareTo(T_FLOOR) >= 0 | |||
| && h.compareTo(H_CEILING) <= 0 && h.compareTo(H_FLOOR) >= 0 | |||
| && i.compareTo(I_CEILING) <= 0 && i.compareTo(I_FLOOR) >= 0 | |||
| && o.compareTo(O_CEILING) <= 0 && o.compareTo(O_FLOOR) >= 0 | |||
| && dp.compareTo(DP_CEILING) <= 0 && dp.compareTo(DP_FLOOR) >= 0 | |||
| && p20.compareTo(P20_CEILING) <= 0 && p20.compareTo(P20_FLOOR) >= 0 | |||
| && h20.compareTo(H20_CEILING) <= 0 && h20.compareTo(H20_FLOOR) >= 0 | |||
| ; | |||
| } | |||
| public void resetData() { | |||
| this.setSensorNo(null); | |||
| this.setSensorNoRadix(null); | |||
| this.temperature = 0.0F; | |||
| this.humidity = 0.0F; | |||
| this.innerPressure = 0.0F; | |||
| this.outerPressure = 0.0F; | |||
| this.diffPressure = 0.0F; | |||
| this.degree20Humidity = 0.0F; | |||
| this.degree20Pressure = 0.0F; | |||
| } | |||
| public void resetData20Degree() { | |||
| this.diffPressure = 0.0F; | |||
| this.degree20Humidity = 0.0F; | |||
| this.degree20Pressure = 0.0F; | |||
| } | |||
| } | |||
| @ -0,0 +1,34 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import com.chad.library.adapter.base.entity.MultiItemEntity; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @Builder | |||
| @NoArgsConstructor | |||
| public class RawData implements MultiItemEntity { | |||
| public static final int TYPE_RECEIVE = 0; | |||
| public static final int TYPE_SEND = 1; | |||
| private int mItemType; | |||
| private String date; | |||
| private String message; | |||
| public RawData(int itemType) { | |||
| mItemType = itemType; | |||
| } | |||
| public RawData(int itemType, String date, String message) { | |||
| mItemType = itemType; | |||
| this.date = date; | |||
| this.message = message; | |||
| } | |||
| @Override | |||
| public int getItemType() { | |||
| return mItemType; | |||
| } | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import org.kymjs.kjframe.database.annotate.Id; | |||
| import org.kymjs.kjframe.database.annotate.Table; | |||
| import org.kymjs.kjframe.database.annotate.Transient; | |||
| /** | |||
| * Created by zy on 2019/2/24. | |||
| * 用来记录传感器信息 | |||
| */ | |||
| @Table(name = "sensor") | |||
| public class Sensor { | |||
| @Id | |||
| public int id; | |||
| /*传感器编号*/ | |||
| public long sensor_id; | |||
| /*弹号*/ | |||
| public String egg_id; | |||
| /*弹型*/ | |||
| public String egg_type; | |||
| /*筒号*/ | |||
| public String tupe_id; | |||
| public String tv_tupe_use_times; | |||
| @Transient | |||
| public int tagBackup = 0; | |||
| } | |||
| @ -0,0 +1,37 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| public class SettingsItem { | |||
| private String name; | |||
| private int iconRes; | |||
| private int position; | |||
| public SettingsItem(String name, int iconRes, int position) { | |||
| this.name = name; | |||
| this.iconRes = iconRes; | |||
| this.position = position; | |||
| } | |||
| public int getPosition() { | |||
| return position; | |||
| } | |||
| public void setPosition(int position) { | |||
| this.position = position; | |||
| } | |||
| public String getName() { | |||
| return name; | |||
| } | |||
| public void setName(String name) { | |||
| this.name = name; | |||
| } | |||
| public int getIconRes() { | |||
| return iconRes; | |||
| } | |||
| public void setIconRes(int iconRes) { | |||
| this.iconRes = iconRes; | |||
| } | |||
| } | |||
| @ -0,0 +1,80 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| public class TestData { | |||
| private String title; | |||
| public String getZhankai() { | |||
| return zhankai; | |||
| } | |||
| public void setZhankai(String zhankai) { | |||
| this.zhankai = zhankai; | |||
| } | |||
| private String zhankai; | |||
| private int tag; | |||
| public boolean isSelect; | |||
| public int temp; | |||
| public int neiYa; | |||
| public int waiYa; | |||
| public int shiDu; | |||
| public int getTemp() { | |||
| return temp; | |||
| } | |||
| public void setTemp(int temp) { | |||
| this.temp = temp; | |||
| } | |||
| public int getNeiYa() { | |||
| return neiYa; | |||
| } | |||
| public void setNeiYa(int neiYa) { | |||
| this.neiYa = neiYa; | |||
| } | |||
| public int getWaiYa() { | |||
| return waiYa; | |||
| } | |||
| public void setWaiYa(int waiYa) { | |||
| this.waiYa = waiYa; | |||
| } | |||
| public int getShiDu() { | |||
| return shiDu; | |||
| } | |||
| public void setShiDu(int shiDu) { | |||
| this.shiDu = shiDu; | |||
| } | |||
| public boolean isSelect() { | |||
| return isSelect; | |||
| } | |||
| public void setSelect(boolean isSelect) { | |||
| this.isSelect = isSelect; | |||
| } | |||
| public String getTitle() { | |||
| return title; | |||
| } | |||
| public void setTitle(String title) { | |||
| this.title = title; | |||
| } | |||
| public int getTag() { | |||
| return tag; | |||
| } | |||
| public void setTag(int tag) { | |||
| this.tag = tag; | |||
| } | |||
| } | |||
| @ -0,0 +1,49 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import org.kymjs.kjframe.database.annotate.Id; | |||
| import org.kymjs.kjframe.database.annotate.Property; | |||
| import org.kymjs.kjframe.database.annotate.Table; | |||
| /** | |||
| * Created by zy on 2019/2/24. | |||
| * 单条汇总测试数据,求取平均值之后的数据 | |||
| */ | |||
| @Table(name = "test_record_total") | |||
| public class TestRecordsTotal { | |||
| /** | |||
| * 测试id | |||
| */ | |||
| @Id | |||
| public long id; | |||
| //记录数据保存的日期标记,方便之后能够查出来 | |||
| public long day_t; | |||
| /*温度*/ | |||
| public float temp; | |||
| /*湿度*/ | |||
| public float Hum; | |||
| /*内压*/ | |||
| public float pressurein; | |||
| /*湿度*/ | |||
| public float Hum20; | |||
| /*内压*/ | |||
| public float pressurein20; | |||
| /*外压*/ | |||
| public float pressureout; | |||
| /*压差*/ | |||
| public float pressure_yacha; | |||
| /*传感器编号*/ | |||
| public long sensor_id; | |||
| /*波特率*/ | |||
| @Property(column = "tupe_id") | |||
| public String botelv; | |||
| /*筒使用次数*/ | |||
| public String tupe_use_times; | |||
| /*测试结束时间*/ | |||
| public long end_time; | |||
| /*数据是否已经备份过*/ | |||
| public int tagBackup = 0; | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import org.kymjs.kjframe.database.annotate.Id; | |||
| import org.kymjs.kjframe.database.annotate.Table; | |||
| /** | |||
| * Created by zy on 2019/2/24. | |||
| */ | |||
| @Table(name = "test_record_item") | |||
| public class TestRecordsitems { | |||
| @Id(autoInc = true) | |||
| public int id; | |||
| /** | |||
| * 对应 TestRecordsTotal 中的id | |||
| */ | |||
| public long test_id; | |||
| /** | |||
| * 对应数据类型 | |||
| * 具体类型,见报文解析字段 | |||
| */ | |||
| public int type; | |||
| /** | |||
| * 测试的数据值 | |||
| */ | |||
| public float value; | |||
| } | |||
| @ -0,0 +1,23 @@ | |||
| package com.handset.serialportsensor.bean; | |||
| import lombok.AllArgsConstructor; | |||
| import lombok.Builder; | |||
| import lombok.Data; | |||
| import lombok.NoArgsConstructor; | |||
| @Data | |||
| @Builder | |||
| @AllArgsConstructor | |||
| @NoArgsConstructor | |||
| public class ThresholdBean { | |||
| public String temperatureFloor; | |||
| public String temperatureCeiling; | |||
| public String humidityFloor; | |||
| public String humidityCeiling; | |||
| public String innerPressureFloor; | |||
| public String innerPressureCeiling; | |||
| public String outerPressureFloor; | |||
| public String outerPressureCeiling; | |||
| public String diffPressureFloor; | |||
| public String diffPressureCeiling; | |||
| } | |||
| @ -0,0 +1,74 @@ | |||
| package com.handset.serialportsensor.constant; | |||
| import android.graphics.Color; | |||
| public class Constant { | |||
| public final static String SENSOR_ID = "sensor_id"; | |||
| public final static String BAUD_RATE = "baud_rate"; | |||
| public static final String ROLE_KEY = "role_key"; | |||
| public static final int NOT_CONNECTED_ROLE = 0; | |||
| public static final int PRIMARY_ROLE = 1; | |||
| public static final int SENIOR_ROLE = 2; | |||
| public static final int BAUD_9600 = 9600; | |||
| public static final int BAUD_19200 = 19200; | |||
| public static final int BAUD_38400 = 38400; | |||
| public static final String DDDD = "DDDD"; | |||
| //ID高16位 | |||
| public static final String ID_HIGH_KEY = "id_high_key"; | |||
| //ID低16位 | |||
| public static final String ID_LOW_KEY = "id_low_key"; | |||
| public static final String THRESHOLD_KEY = "id_key"; | |||
| public static final String idHigh1 = "id1"; | |||
| public static final String idHigh2 = "id2"; | |||
| public static final String idHigh3 = "id3"; | |||
| public static final String idHigh4 = "id4"; | |||
| public static final int READ_TIME_OUT = 3000; | |||
| public static final int READ_TIME_OUT_TIME = 1000;//延迟1秒 | |||
| public static final String FORMAT_FLOAT_PATTERN = "0.00"; | |||
| public final static int red = Color.rgb((255), (0), (0)); | |||
| public final static int green = Color.rgb((0), (255), (0)); | |||
| public final static int yellow = Color.rgb((255), (255), (0)); | |||
| public final static int grey = Color.rgb((0x9d), (0x9d), (0x9d)); | |||
| public static final class Command { | |||
| public static final int COMMAND_25 = 0x25;//ID查询 | |||
| public static final int COMMAND_26 = 0x26;//ID上报 | |||
| public static final int COMMAND_27 = 0x27;//检测仪模式切换 | |||
| public static final int COMMAND_28 = 0x28;//模式切换结果指令上报 | |||
| public static final int COMMAND_29 = 0x29;//温度指令上报 | |||
| public static final int COMMAND_2A = 0x2A;//内压指令上报 | |||
| public static final int COMMAND_2B = 0x2B;//湿度指令上报 | |||
| public static final int COMMAND_2C = 0x2C;//外压指令上报 | |||
| public static final int COMMAND_2D = 0x2D;//差压指令上报 | |||
| public static final int COMMAND_2E = 0x2E;//20度湿度指令上报 | |||
| public static final int COMMAND_2F = 0x2F;//20度内压指令上报 | |||
| public static final int COMMAND_30 = 0x30;//弹号读取 | |||
| public static final int COMMAND_31 = 0x31;//弹号指令上报 | |||
| public static final int COMMAND_32 = 0x32;//弹号设置 | |||
| public static final int COMMAND_33 = 0x33;//弹号设置指令上报 | |||
| public static final int COMMAND_34 = 0x34;//筒号读取 | |||
| public static final int COMMAND_35 = 0x35;//筒号指令上报 | |||
| public static final int COMMAND_36 = 0x36;//筒号设置 | |||
| public static final int COMMAND_37 = 0x37;//筒号设置指令上报 | |||
| public static final int COMMAND_38 = 0x38;//弹筒使用次数读取 | |||
| public static final int COMMAND_39 = 0x39;//弹筒使用次数指令上报 | |||
| public static final int COMMAND_3A = 0x3A;//弹筒使用次数设置 | |||
| public static final int COMMAND_3B = 0x3B;//弹筒使用次数设置指令上报 | |||
| public static final int COMMAND_3C = 0x3C;//波特率设置 | |||
| public static final int COMMAND_3D = 0x3D;//波特率设置结果指令上报 | |||
| public static final int COMMAND_3E = 0x3E; //弹型读取 | |||
| public static final int COMMAND_3F = 0x3F; //弹型读取回复 | |||
| public static final int COMMAND_40 = 0x40; //弹型设置 | |||
| public static final int COMMAND_41 = 0x41; //弹型设置回复 | |||
| public static final int COMMAND_49 = 0x49;//恢复出厂设置 | |||
| public static final int COMMAND_4A = 0x4A;//恢复出厂设置结果返回 | |||
| public static final int COMMAND_50 = 0x50;//传感器ID设置 | |||
| public static final int COMMAND_51 = 0x51;//传感器ID设置 | |||
| } | |||
| } | |||
| @ -0,0 +1,55 @@ | |||
| package com.handset.serialportsensor.db; | |||
| import android.content.Context; | |||
| import android.database.Cursor; | |||
| import android.database.sqlite.SQLiteDatabase; | |||
| import org.kymjs.kjframe.KJDB; | |||
| /** | |||
| * Created by zy on 2019/3/7. | |||
| */ | |||
| public class DBUpdateHelperMY implements KJDB.DbUpdateListener { | |||
| private static final String TAG = com.suntiago.dblib.DBUpdateHelper.class.getSimpleName(); | |||
| public static final int DATABASE_VERSION = 2; | |||
| public DBUpdateHelperMY() { | |||
| } | |||
| public void onCreate(Context context, SQLiteDatabase sqLiteDatabase) { | |||
| } | |||
| public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { | |||
| if (oldVersion < 2) { | |||
| if (tabbleIsExist(db, "sensor")) { | |||
| db.execSQL("ALTER TABLE media ADD COLUMN tv_tupe_use_times String DEFAULT \'\';"); | |||
| } | |||
| } | |||
| } | |||
| public boolean tabbleIsExist(SQLiteDatabase db, String tableName) { | |||
| boolean result = false; | |||
| if (tableName == null) { | |||
| return false; | |||
| } | |||
| Cursor cursor = null; | |||
| try { | |||
| //这里表名可以是Sqlite_master | |||
| String sql = "select count(*) as c from htjc_sensor_history where type ='table' and name ='" + tableName + "'"; | |||
| cursor = db.rawQuery(sql, null); | |||
| if (cursor.moveToNext()) { | |||
| int count = cursor.getInt(0); | |||
| if (count > 0) { | |||
| result = true; | |||
| } | |||
| } | |||
| } catch (Exception e) { | |||
| // TODO: handle exception | |||
| } | |||
| return result; | |||
| } | |||
| } | |||
| @ -0,0 +1,15 @@ | |||
| package com.handset.serialportsensor.presenter; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| public interface SurfaceContract { | |||
| interface ISerialView { | |||
| void onSerialOpen(boolean isOpen); | |||
| void onSerialData(RawData rawData); | |||
| void onSerialBaudRate(Integer baudRate); | |||
| void onSerialError(Integer errorCode); | |||
| } | |||
| } | |||
| @ -0,0 +1,315 @@ | |||
| package com.handset.serialportsensor.presenter; | |||
| import android.os.SystemClock; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import com.blankj.utilcode.util.SPUtils; | |||
| import com.blankj.utilcode.util.ToastUtils; | |||
| import com.handset.serialportlib.CRCUtils; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.activity.SPKey; | |||
| import com.handset.serialportsensor.bean.RawData; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import com.handset.serialportlib.SerialPort; | |||
| import com.handset.serialportsensor.utils.SplitUtils; | |||
| import io.reactivex.BackpressureStrategy; | |||
| import io.reactivex.Flowable; | |||
| import io.reactivex.FlowableOnSubscribe; | |||
| import io.reactivex.Observable; | |||
| import io.reactivex.ObservableEmitter; | |||
| import io.reactivex.ObservableOnSubscribe; | |||
| import io.reactivex.android.schedulers.AndroidSchedulers; | |||
| import io.reactivex.disposables.Disposable; | |||
| import io.reactivex.schedulers.Schedulers; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.util.LinkedHashSet; | |||
| import org.joda.time.DateTime; | |||
| public class SurfacePresenter { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private final static String POWER_EN_PATH = "/sys/class/peijian_dev/function/PeijianPowerEn"; | |||
| private final static String POGO_WAKE = "/sys/class/peijian_dev/function/pogo_wake"; | |||
| private final static String SERIAL_PATH = "dev/ttyHSL1"; | |||
| private final static Integer SERIAL_BAUD_RATE = 38400; | |||
| private final static String mDateFormat = "HH:mm:ss:SSS"; | |||
| private SurfaceContract.ISerialView mSerialView; | |||
| private LinkedHashSet<String> mSendHistory; | |||
| private int mCheckDigit; | |||
| private int mDataBits; | |||
| private int mStopBit; | |||
| private boolean isHexReceive; | |||
| private boolean isHexSend; | |||
| private boolean isShowSend; | |||
| private boolean isShowTime; | |||
| private SerialPort mSerialPort; | |||
| private boolean isInterrupted; | |||
| private Disposable mReceiveDisposable; | |||
| private ObservableEmitter<String> mEmitter; | |||
| private Disposable mSendDisposable; | |||
| public SurfacePresenter(SurfaceContract.ISerialView view) { | |||
| mSerialView = view; | |||
| isHexReceive = true; | |||
| isHexSend = SPUtils.getInstance().getBoolean(SPKey.SETTING_SEND_TYPE, (true)); | |||
| isShowSend = SPUtils.getInstance().getBoolean(SPKey.SETTING_RECEIVE_SHOW_SEND, (true)); | |||
| isShowTime = SPUtils.getInstance().getBoolean(SPKey.SETTING_RECEIVE_SHOW_TIME, (true)); | |||
| try { | |||
| mSendHistory = (LinkedHashSet<String>) SPUtils.getInstance().getStringSet(SPKey.SEND_HISTORY, new LinkedHashSet<>((30))); | |||
| } catch (ClassCastException e) { | |||
| e.printStackTrace(); | |||
| mSendHistory = new LinkedHashSet<>((30)); | |||
| } | |||
| } | |||
| private void refreshValueFormSp() { | |||
| //String mPath = SPUtils.getInstance().getString(SPKey.SERIAL_PORT, ("")); | |||
| //int mBaudRate = Integer.parseInt(SPUtils.getInstance().getString(SPKey.BAUD_RATE, ("9600"))); | |||
| mCheckDigit = Integer.parseInt(SPUtils.getInstance().getString(SPKey.CHECK_DIGIT, ("0"))); | |||
| mDataBits = Integer.parseInt(SPUtils.getInstance().getString(SPKey.DATA_BITS, ("8"))); | |||
| mStopBit = Integer.parseInt(SPUtils.getInstance().getString(SPKey.STOP_BIT, ("1"))); | |||
| } | |||
| public void open() { | |||
| refreshValueFormSp(); | |||
| try { | |||
| mSerialPort = new SerialPort(new File(SERIAL_PATH), SERIAL_BAUD_RATE, mCheckDigit, mDataBits, mStopBit, (0)); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| mSerialPort = null; | |||
| ToastUtils.showLong(R.string.open_serial_port_failure); | |||
| } | |||
| if (mSerialPort != null) { | |||
| this.initBLNStatus('1'); | |||
| isInterrupted = false; | |||
| try { | |||
| Thread.sleep(3000); | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| onReceiveSubscribe(); | |||
| onSendSubscribe(); | |||
| mSerialView.onSerialOpen((mSerialPort != null)); | |||
| //ToastUtils.showLong(R.string.open_serial_port_success); | |||
| } else { | |||
| mSerialView.onSerialError((0)); | |||
| } | |||
| } | |||
| public void open(Integer baudRate) { | |||
| if (baudRate == null) { | |||
| Log.i(logTag, ("onSerialBaudRate null")); | |||
| return; | |||
| } | |||
| refreshValueFormSp(); | |||
| try { | |||
| Log.i(logTag, ("onSerialBaudRate: " + baudRate)); | |||
| mSerialPort = new SerialPort(new File(SERIAL_PATH), baudRate, mCheckDigit, mDataBits, mStopBit, (0)); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| ToastUtils.showLong(R.string.open_serial_port_failure); | |||
| } | |||
| if (mSerialPort != null) { | |||
| this.initBLNStatus('1'); | |||
| isInterrupted = false; | |||
| try { | |||
| Thread.sleep(3000); | |||
| } catch (InterruptedException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| onReceiveSubscribe(); | |||
| onSendSubscribe(); | |||
| } | |||
| mSerialView.onSerialOpen((mSerialPort != null)); | |||
| } | |||
| public void close() { | |||
| Log.i(logTag, ("closing!!!")); | |||
| this.initBLNStatus('0'); | |||
| isInterrupted = true; | |||
| disposable(mReceiveDisposable); | |||
| disposable(mSendDisposable); | |||
| mEmitter = null; | |||
| mSerialPort = null; | |||
| mSerialView.onSerialOpen((false)); | |||
| } | |||
| public void initBLNStatus(char status) { | |||
| setBLNStatus(status, POWER_EN_PATH); | |||
| setBLNStatus(status, POGO_WAKE); | |||
| } | |||
| private void setBLNStatus(char status, String path) { | |||
| FileOutputStream fos = null; | |||
| try { | |||
| File file = new File(path); | |||
| if (file.exists()) { | |||
| fos = new FileOutputStream(file); | |||
| fos.write(status); | |||
| fos.flush(); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } finally { | |||
| if (fos != null) { | |||
| try { | |||
| fos.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| private void onSendSubscribe() { | |||
| mSendDisposable = | |||
| Observable.create((ObservableOnSubscribe<String>) emitter -> mEmitter = emitter) | |||
| .filter(s -> !TextUtils.isEmpty(s)) | |||
| .doOnNext(s -> mSendHistory.add(s)) | |||
| .doOnNext(s -> { | |||
| Log.i(logTag, ("Sent: " + addSpace(s.toUpperCase()))); | |||
| mSerialPort.getOutputStream().write(isHexSend ? ByteUtils.hexStrToBytes(s) : ByteUtils.strToAsciiBytes(s)); | |||
| mSerialPort.getOutputStream().flush(); | |||
| }) | |||
| .observeOn(AndroidSchedulers.mainThread()) | |||
| .filter(s -> isShowSend) | |||
| .subscribe(s -> { | |||
| //Log.d(logTag, ("sender: " + addSpace(s.toUpperCase()))); | |||
| mSerialView.onSerialData(new RawData(RawData.TYPE_SEND, isShowTime ? DateTime.now().toString(mDateFormat) : "", addSpace(s.toUpperCase()))); | |||
| }, Throwable::printStackTrace); | |||
| } | |||
| private void onReceiveSubscribe() { | |||
| mReceiveDisposable = | |||
| Flowable.create((FlowableOnSubscribe<byte[]>) emitter -> { | |||
| int first, available; | |||
| InputStream is = mSerialPort.getInputStream(); | |||
| while (!isInterrupted | |||
| && mSerialPort != null | |||
| && is != null | |||
| && (first = is.read()) != -1) { | |||
| do { | |||
| available = is.available(); | |||
| SystemClock.sleep((1)); | |||
| } while (available != is.available()); | |||
| available = is.available(); | |||
| byte[] bytes = new byte[available + 1]; | |||
| int n = is.read(bytes, (1), available); | |||
| Log.d(logTag, ("Received n: " + n + ", raw: " + ByteUtils.bytesToHexStr(bytes))); | |||
| bytes[0] = (byte) (first & 0xFF); | |||
| Log.d(logTag, ("Received first: " + first + ", raw: " + ByteUtils.bytesToHexStr(bytes))); | |||
| emitter.onNext(bytes); | |||
| } | |||
| Log.d(logTag, ("onReceiveSubscribe close:")); | |||
| close(); | |||
| }, BackpressureStrategy.MISSING | |||
| ).retry().map(bytes -> isHexReceive ? ByteUtils.bytesToHexStr(bytes) : ByteUtils.bytesToAscii(bytes)) | |||
| .filter(this::validate) | |||
| .filter(this::crcVerify) | |||
| .map(this::getBody) | |||
| .subscribeOn(Schedulers.single()) | |||
| .observeOn(AndroidSchedulers.mainThread()) | |||
| .subscribe( | |||
| it -> { | |||
| Log.v(logTag, ("Received: " + addSpace(it))); | |||
| mSerialView.onSerialData(new RawData(RawData.TYPE_RECEIVE, isShowTime ? DateTime.now().toString(mDateFormat) : "", it)); | |||
| }, Throwable::printStackTrace | |||
| ); | |||
| } | |||
| private boolean validate(String raw) { | |||
| try { | |||
| Log.v(logTag, ("len: " + raw.length())); | |||
| return !TextUtils.isEmpty(raw) && raw.length() >= 22; | |||
| } catch (Exception e) { | |||
| Log.v(logTag, ("validate, exp: " + e.getMessage())); | |||
| return false; | |||
| } | |||
| } | |||
| private boolean crcVerify(String rawData) { | |||
| try { | |||
| Log.v(logTag, ("crcVerify: " + rawData)); | |||
| for (String str : SplitUtils.split(rawData)) { | |||
| if (TextUtils.isEmpty(str) || str.length() < 4) continue; | |||
| if (!CRCUtils.genCrc(str.substring(4, str.length() - 4)).equals(str.substring(str.length() - 4))) { | |||
| Log.w(logTag, ("str: " + str + " crc fail!")); | |||
| return (str.charAt(12) == '0' && str.charAt(13) == '0' && str.charAt(14) == '2' && str.charAt(15) == '6'); | |||
| } | |||
| } | |||
| return true; | |||
| } catch (Exception e) { | |||
| Log.v(logTag, ("crcVerify, exp: " + e.getMessage())); | |||
| return false; | |||
| } | |||
| } | |||
| private String getBody(String raw) { | |||
| return raw; | |||
| } | |||
| private String addSpace(String s) { | |||
| if (s.length() % 2 == 0) { | |||
| StringBuilder builder = new StringBuilder(); | |||
| char[] array = s.toCharArray(); | |||
| int length = array.length; | |||
| for (int i = 0; i < length; i += 2) { | |||
| if (i != 0 && i <= length - 2) { | |||
| builder.append(" "); | |||
| } | |||
| builder.append(array[i]); | |||
| builder.append(array[i + 1]); | |||
| } | |||
| return builder.toString(); | |||
| } | |||
| return s; | |||
| } | |||
| public void write(String message) { | |||
| if (mEmitter == null) { | |||
| ToastUtils.showLong(R.string.open_serial_port_first); | |||
| return; | |||
| } | |||
| if (TextUtils.isEmpty(message)) { | |||
| Log.w(logTag, "Message is empty!"); | |||
| return; | |||
| } | |||
| mEmitter.onNext(message); | |||
| } | |||
| public void onDestroy() { | |||
| close(); | |||
| SPUtils.getInstance().put(SPKey.SEND_HISTORY, mSendHistory); | |||
| } | |||
| private void disposable(Disposable disposable) { | |||
| if (disposable != null && !disposable.isDisposed()) { | |||
| disposable.dispose(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,78 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| /** | |||
| * @author dizhou | |||
| */ | |||
| public class CRC16Utils { | |||
| /* | |||
| * CCITT标准CRC16(1021)余数表 CRC16-CCITT ISO HDLC, ITU X.25, x16+x12+x5+1 多项式 | |||
| * 高位在先时生成多项式 Gm=0x11021 低位在先时生成多项式,Gm=0x8408 本例采用高位在先 | |||
| */ | |||
| private static int crc16_ccitt_table[] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, | |||
| 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, | |||
| 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, | |||
| 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, | |||
| 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, | |||
| 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, | |||
| 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, | |||
| 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, | |||
| 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, | |||
| 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, | |||
| 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, | |||
| 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, | |||
| 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, | |||
| 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, | |||
| 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, | |||
| 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, | |||
| 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; | |||
| public static int getCRC1021(byte bytes[]) { | |||
| return getCRC2(bytes); | |||
| } | |||
| public static int getCRC1021_old(byte bytes[]) { | |||
| int crc = 0x00; // initial value | |||
| int polynomial = 0x1021; | |||
| for (int index = 0; index < bytes.length; index++) { | |||
| byte b = bytes[index]; | |||
| for (int i = 0; i < 8; i++) { | |||
| boolean bit = ((b >> (7 - i) & 1) == 1); | |||
| boolean c15 = ((crc >> 15 & 1) == 1); | |||
| crc <<= 1; | |||
| if (c15 ^ bit) crc ^= polynomial; | |||
| } | |||
| } | |||
| crc &= 0xffff; | |||
| return crc; | |||
| } | |||
| public static int getCRC2(byte[] bytes) { | |||
| int CRC = 0xffff; | |||
| int POLYNOMIAL = 0xA001; | |||
| int i, j; | |||
| for (i = 0; i < bytes.length; i++) { | |||
| CRC ^= ((int) bytes[i] & 0x00ff); | |||
| for (j = 0; j < 8; j++) { | |||
| if ((CRC & 0x0001) != 0) { | |||
| CRC >>= 1; | |||
| CRC ^= POLYNOMIAL; | |||
| } else { | |||
| CRC >>= 1; | |||
| } | |||
| } | |||
| } | |||
| return CRC ; | |||
| } | |||
| // 测试 | |||
| // public static void main(String[] args) { | |||
| // // 0xf360 DD DD 13 01 03 EF 00 29 04 DB 08 00 00 1B 42 | |||
| // byte[] a = new byte[]{(byte) 0x13, (byte) 0x01, (byte) 0x03 | |||
| // , (byte) 0xef | |||
| // , (byte) 0x00, (byte) 0x29, (byte) 0x04, (byte) 0xdb, (byte) 0x08, (byte) 0x00, (byte) 0x00}; | |||
| // int crc2 = getCRC1021(a); | |||
| // System.out.println("结果=" + Integer.toHexString(crc2)); | |||
| // | |||
| // } | |||
| } | |||
| @ -0,0 +1,245 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| import android.content.Intent; | |||
| import android.content.pm.PackageInfo; | |||
| import android.content.pm.PackageManager; | |||
| import android.content.pm.PackageManager.NameNotFoundException; | |||
| import android.os.Build; | |||
| import android.os.Environment; | |||
| import android.os.Looper; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import android.widget.Toast; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.io.PrintWriter; | |||
| import java.io.StringWriter; | |||
| import java.io.Writer; | |||
| import java.lang.Thread.UncaughtExceptionHandler; | |||
| import java.lang.reflect.Field; | |||
| import java.text.DateFormat; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.Locale; | |||
| import java.util.Map; | |||
| /** | |||
| * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. | |||
| * | |||
| * @author Jeremy | |||
| */ | |||
| public class CrashHandler implements UncaughtExceptionHandler { | |||
| public static final String TAG = "HANDSET-JE002-EX"; | |||
| private static final String BROADCAST_ACTION = "com.ss.permission.crash_log_update"; | |||
| //private LocalBroadcastManager mLocalBroadcastManager; | |||
| //系统默认的UncaughtException处理类 | |||
| private UncaughtExceptionHandler mDefaultHandler; | |||
| //程序的Context对象 | |||
| private Context mContext; | |||
| //用来存储设备信息和异常信息 | |||
| private Map<String, String> infos = new HashMap<>(); | |||
| //用于格式化日期,作为日志文件名的一部分 | |||
| private DateFormat formatter = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss", Locale.CHINA); | |||
| private String packageName = ""; | |||
| private static class CrashHandlerHolder { | |||
| private static CrashHandler instance = new CrashHandler(); | |||
| } | |||
| /** | |||
| * 保证只有一个CrashHandler实例 | |||
| */ | |||
| private CrashHandler() { | |||
| } | |||
| /** | |||
| * 获取CrashHandler实例 ,单例模式 | |||
| */ | |||
| public static CrashHandler getInstance() { | |||
| return CrashHandlerHolder.instance; | |||
| } | |||
| private String getCrashLogPath() { | |||
| return getSavePath(); | |||
| } | |||
| private static String getSavePath() { | |||
| return Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "crashlog/"; | |||
| } | |||
| /** | |||
| * 初始化 | |||
| * use init(Context context) instead | |||
| * | |||
| * @param context context | |||
| */ | |||
| @Deprecated | |||
| public void init(Context context, String com, String pkgId) { | |||
| mContext = context; | |||
| //获取系统默认的UncaughtException处理器 | |||
| mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); | |||
| //mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext); | |||
| //设置该CrashHandler为程序的默认处理器 | |||
| Thread.setDefaultUncaughtExceptionHandler(this); | |||
| if (!TextUtils.isEmpty(pkgId)) { | |||
| this.packageName = pkgId; | |||
| } | |||
| } | |||
| public void init(Context context) { | |||
| mContext = context; | |||
| //获取系统默认的UncaughtException处理器 | |||
| mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); | |||
| //mLocalBroadcastManager = LocalBroadcastManager.getInstance(mContext); | |||
| //设置该CrashHandler为程序的默认处理器 | |||
| Thread.setDefaultUncaughtExceptionHandler(this); | |||
| String pkgId = context.getPackageName().replace(".", "_") + "_"; | |||
| if (!TextUtils.isEmpty(pkgId)) { | |||
| this.packageName = pkgId; | |||
| } | |||
| } | |||
| /** | |||
| * 当UncaughtException发生时会转入该函数来处理 | |||
| */ | |||
| @Override | |||
| public void uncaughtException(Thread thread, Throwable ex) { | |||
| if (!handleException(ex) && mDefaultHandler != null) { | |||
| //如果用户没有处理则让系统默认的异常处理器来处理 | |||
| mDefaultHandler.uncaughtException(thread, ex); | |||
| } else { | |||
| try { | |||
| Thread.sleep(3000); | |||
| } catch (InterruptedException e) { | |||
| Log.e(TAG, "error : ", e); | |||
| } | |||
| //退出程序 | |||
| android.os.Process.killProcess(android.os.Process.myPid()); | |||
| System.exit(1); | |||
| } | |||
| } | |||
| /** | |||
| * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. | |||
| * | |||
| * @param ex 异常 | |||
| * @return true:如果处理了该异常信息;否则返回false. | |||
| */ | |||
| private boolean handleException(Throwable ex) { | |||
| if (ex == null) { | |||
| return false; | |||
| } | |||
| //使用Toast来显示异常信息 | |||
| new Thread() { | |||
| @Override | |||
| public void run() { | |||
| Looper.prepare(); | |||
| Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show(); | |||
| Looper.loop(); | |||
| } | |||
| }.start(); | |||
| //收集设备参数信息 | |||
| collectDeviceInfo(mContext); | |||
| //打印异常log,以供分析调试 | |||
| ex.printStackTrace(); | |||
| //保存日志文件 | |||
| String path = saveCrashInfo2File(ex); | |||
| Log.d(TAG, BROADCAST_ACTION); | |||
| Intent intent = new Intent(); | |||
| intent.setAction(BROADCAST_ACTION); | |||
| intent.putExtra("path", path); | |||
| intent.putExtra("pkgName", mContext.getPackageName()); | |||
| mContext.sendBroadcast(intent); | |||
| return true; | |||
| } | |||
| /** | |||
| * 收集设备参数信息 | |||
| * | |||
| * @param ctx 异常 | |||
| */ | |||
| private void collectDeviceInfo(Context ctx) { | |||
| try { | |||
| PackageManager pm = ctx.getPackageManager(); | |||
| PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); | |||
| if (pi != null) { | |||
| String versionName = pi.versionName == null ? "null" : pi.versionName; | |||
| String versionCode = pi.versionCode + ""; | |||
| infos.put("versionName", versionName); | |||
| infos.put("versionCode", versionCode); | |||
| } | |||
| } catch (NameNotFoundException e) { | |||
| Log.e(TAG, "An error occur when collect package info", e); | |||
| } | |||
| Field[] fields = Build.class.getDeclaredFields(); | |||
| for (Field field : fields) { | |||
| try { | |||
| field.setAccessible(true); | |||
| infos.put(field.getName(), field.get(null).toString()); | |||
| Log.d(TAG, field.getName() + " : " + field.get(null)); | |||
| } catch (Exception e) { | |||
| Log.e(TAG, "An error occur when collect crash info", e); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 保存错误信息到文件中 | |||
| * | |||
| * @param ex 异常 | |||
| * @return 返回文件名称, 便于将文件传送到服务器 | |||
| */ | |||
| private String saveCrashInfo2File(Throwable ex) { | |||
| StringBuilder sb = new StringBuilder(); | |||
| for (Map.Entry<String, String> entry : infos.entrySet()) { | |||
| String key = entry.getKey(); | |||
| String value = entry.getValue(); | |||
| sb.append(key + "=" + value + "\n"); | |||
| } | |||
| Writer writer = new StringWriter(); | |||
| PrintWriter printWriter = new PrintWriter(writer); | |||
| ex.printStackTrace(printWriter); | |||
| Throwable cause = ex.getCause(); | |||
| while (cause != null) { | |||
| cause.printStackTrace(printWriter); | |||
| cause = cause.getCause(); | |||
| } | |||
| printWriter.close(); | |||
| String result = writer.toString(); | |||
| sb.append(result); | |||
| try { | |||
| long timestamp = System.currentTimeMillis(); | |||
| String time = formatter.format(new Date()); | |||
| String pkgNamePath = packageName.replace(".", "_"); | |||
| String fileName = "crash_" + pkgNamePath + "_" + time + "_" + timestamp + ".log"; | |||
| String path = getCrashLogPath(); | |||
| if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { | |||
| File dir = new File(path); | |||
| if (!dir.exists()) { | |||
| boolean res = dir.mkdirs(); | |||
| Log.v(TAG, ("saveCrashInfo2File res: " + res)); | |||
| } | |||
| FileOutputStream fos = new FileOutputStream(path + fileName); | |||
| fos.write(sb.toString().getBytes()); | |||
| fos.close(); | |||
| } | |||
| return path + fileName; | |||
| } catch (Exception e) { | |||
| Log.e(TAG, "an error occur while writing file...", e); | |||
| } | |||
| return null; | |||
| } | |||
| } | |||
| @ -0,0 +1,49 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| /** | |||
| * 从AndroidOne上导入的 | |||
| * Created by LiGang on 2016/6/1. | |||
| */ | |||
| public class DateStyle { | |||
| /** | |||
| * 默认时间格式 | |||
| */ | |||
| public static final String MM_DD = "MM-dd"; | |||
| public static final String YYYY_MM = "yyyy-MM"; | |||
| public static final String YYYYMM = "yyyyMM"; | |||
| public static final String YYYY_MM_DD = "yyyy-MM-dd"; | |||
| public static final String MM_DD_HH_MM = "MM-dd HH:mm"; | |||
| public static final String MM_DD_HH_MM_SS = "MM-dd HH:mm:ss"; | |||
| public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd-HH-mm"; | |||
| public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; | |||
| /** | |||
| * 英文时间格式 | |||
| */ | |||
| public static final String MM_DD_EN = "MM/dd"; | |||
| public static final String YYYY_MM_EN = "yyyy/MM"; | |||
| public static final String YYYY_MM_DD_EN = "yyyy/MM/dd"; | |||
| public static final String MM_DD_HH_MM_EN = "MM/DD HH:mm"; | |||
| public static final String MM_DD_HH_MM_SS_EN = "MM/dd HH:mm:ss"; | |||
| public static final String YYYY_MM_DD_HH_MM_EN = "yyyy/MM/dd HH:mm"; | |||
| public static final String YYYY_MM_DD_HH_MM_SS_EN = "yyyy/MM/dd HH:mm:ss"; | |||
| /** | |||
| * 中文时间格式 | |||
| */ | |||
| public static final String MM_DD_CN = "MM月dd日"; | |||
| public static final String YYYY_MM_CN = "yyyy年MM月"; | |||
| public static final String YYYY_MM_DD_CN = "yyyy年MM月dd日"; | |||
| public static final String MM_DD_HH_MM_CN = "MM月dd日 HH:mm"; | |||
| public static final String MM_DD_HH_MM_SS_CN = "MM月dd日 HH:mm:ss"; | |||
| public static final String YYYY_MM_DD_HH_MM_CN = "yyyy年MM月dd日 HH:mm"; | |||
| public static final String YYYY_MM_DD_HH_MM_SS_CN = "yyyy年MM月dd日 HH:mm:ss"; | |||
| /** | |||
| * 具体时间格式 | |||
| */ | |||
| public static final String HH_MM = "HH:mm"; | |||
| public static final String HH_MM_SS = "HH:mm:ss"; | |||
| } | |||
| @ -0,0 +1,322 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.annotation.SuppressLint; | |||
| import android.content.Context; | |||
| import java.text.ParseException; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import java.util.Date; | |||
| import java.util.GregorianCalendar; | |||
| import java.util.Locale; | |||
| import java.util.TimeZone; | |||
| /** | |||
| * 日期显示,格式化。 | |||
| * Created by LiGang on 2016/6/1. | |||
| */ | |||
| @SuppressWarnings("ALL") | |||
| @SuppressLint("SimpleDateFormat") | |||
| public class DateUtils { | |||
| /** | |||
| * 获取当前时间 | |||
| * 格式 : "yyyy_MM_dd" | |||
| * | |||
| * @return | |||
| */ | |||
| public static String currentDateTime() { | |||
| return currentDateTime(DateStyle.YYYY_MM_DD); | |||
| } | |||
| /** | |||
| * 获取当前时间 | |||
| * 指定样式 | |||
| * | |||
| * @param dateStyle 格式 | |||
| * @return | |||
| */ | |||
| public static String currentDateTime(String dateStyle) { | |||
| SimpleDateFormat formatter = new SimpleDateFormat(dateStyle); | |||
| return formatter.format(new Date()); | |||
| } | |||
| /** | |||
| * 格式化时间 | |||
| * | |||
| * @param date 时间 | |||
| * @param style 格式 | |||
| * @return 格式化结果 | |||
| */ | |||
| public static String format(Date date, String style) { | |||
| SimpleDateFormat format = new SimpleDateFormat(style); | |||
| return format.format(date); | |||
| } | |||
| /** | |||
| * 今天零点的时间 | |||
| * | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Date startOfDate(Date date) { | |||
| long time = date.getTime() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset();// 今天零点零分零秒的毫秒数 | |||
| return new Date(time); | |||
| } | |||
| /** | |||
| * 第一个时间是不是在第二个时间之前 | |||
| * | |||
| * @param date | |||
| * @param now | |||
| * @return | |||
| */ | |||
| public static boolean before(Date date, Date now) { | |||
| if (date.before(now)) { | |||
| return true; | |||
| } else { | |||
| long between = date.getTime() - now.getTime(); | |||
| if (between > (24 * 3600000)) { | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| /** | |||
| * 今天23:59:59的时间 | |||
| * | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static Date endOfDate(Date date) { | |||
| long time = date.getTime() / (1000 * 3600 * 24) * (1000 * 3600 * 24) - TimeZone.getDefault().getRawOffset() + 24 * 60 * 60 * 1000 - 1; | |||
| return new Date(time); | |||
| } | |||
| /** | |||
| * 格式化timestamp格式的时间,以秒为单位 | |||
| * | |||
| * @param timestamp 秒 | |||
| * @param dateStyle 格式 | |||
| * @return 格式化结果 | |||
| */ | |||
| public static String formatSecondTimestamp(long timestamp, String dateStyle) { | |||
| Calendar c = Calendar.getInstance(); | |||
| c.setTimeInMillis(timestamp * 1000); | |||
| return format(c.getTime(), dateStyle); | |||
| } | |||
| /** | |||
| * 格式化timestamp格式的时间,以秒为单位 | |||
| * | |||
| * @param timestamp 毫秒 | |||
| * @param dateStyle 格式 | |||
| * @return 格式化结果 | |||
| */ | |||
| public static String formatMilliesTimestamp(long timestamp, String dateStyle) { | |||
| Calendar c = Calendar.getInstance(); | |||
| c.setTimeInMillis(timestamp ); | |||
| return format(c.getTime(), dateStyle); | |||
| } | |||
| /** | |||
| * 根据时间戳,格式化日期,当天只返回时间,其他返回日期 | |||
| * | |||
| * @param timestamp 秒 | |||
| * @return 格式化的时间 | |||
| */ | |||
| public static String getCurrentTimeIFCurrentDayOrDate(long timestamp) { | |||
| Calendar now = Calendar.getInstance(); | |||
| Calendar c = Calendar.getInstance(); | |||
| c.setTimeInMillis(timestamp * 1000); | |||
| if (c.get(Calendar.YEAR) == now.get(Calendar.YEAR) | |||
| && c.get(Calendar.MONTH) == now.get(Calendar.MONTH) | |||
| && c.get(Calendar.DATE) == now.get(Calendar.DATE)) { | |||
| return format(c.getTime(), DateStyle.HH_MM); | |||
| } | |||
| return format(c.getTime(), DateStyle.YYYY_MM_DD); | |||
| } | |||
| /** | |||
| * 获取yyyy-MM-dd格式日期 | |||
| * | |||
| * @param context | |||
| * @param date | |||
| * @return | |||
| */ | |||
| public static String getDateFormatYYYYMMDD(Context context, Date date) { | |||
| if (context == null) return null; | |||
| SimpleDateFormat format = new SimpleDateFormat(DateStyle.YYYY_MM_DD); | |||
| return format.format(date); | |||
| } | |||
| /** | |||
| * 把一个日期格式的字符串转化为日期 | |||
| * | |||
| * @param context | |||
| * @param dateStr | |||
| * @return | |||
| * @throws ParseException | |||
| */ | |||
| public static Date parseStringToDate(Context context, String dateStr) throws ParseException { | |||
| if (context == null || dateStr == null) return null; | |||
| SimpleDateFormat format = new SimpleDateFormat(DateStyle.YYYY_MM_DD); | |||
| return format.parse(dateStr); | |||
| } | |||
| /** | |||
| * 将一个时间转换为提示性字符串 | |||
| * | |||
| * @param timeStamp 秒值 | |||
| * @return | |||
| */ | |||
| public static String convertTimeToFormat(long timeStamp) { | |||
| int current = (int) (System.currentTimeMillis() / 1000 - timeStamp); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| String today = DateUtils.format(calendar.getTime(), "yyyy-MM-dd"); | |||
| String currentYear = DateUtils.format(calendar.getTime(), "yyyy"); | |||
| calendar.setTimeInMillis(timeStamp * 1000); | |||
| String publishDay = DateUtils.format(calendar.getTime(), "yyyy-MM-dd"); | |||
| String publishYear = DateUtils.format(calendar.getTime(), "yyyy"); | |||
| String publishMonth = DateUtils.format(calendar.getTime(), "MM-dd HH:mm"); | |||
| if (current < 60) { | |||
| return "刚刚"; | |||
| } else if (current < 3600) { | |||
| if (today.equals(publishDay)) { | |||
| return current / 60 + "分钟前"; | |||
| } else { | |||
| return publishMonth; | |||
| } | |||
| } else if (current < 86400) { | |||
| if (today.equals(publishDay)) { | |||
| return current / 3600 + "小时前"; | |||
| } else { | |||
| return publishMonth; | |||
| } | |||
| } else if (current < 31536000) { | |||
| if (publishYear.equals(currentYear)) { | |||
| return publishMonth; | |||
| } else { | |||
| return publishDay; | |||
| } | |||
| } else { | |||
| return publishDay; | |||
| } | |||
| } | |||
| /** | |||
| * 将一个日期转换为提示性时间字符串 | |||
| * | |||
| * @param date 日期 | |||
| * @return | |||
| */ | |||
| public static String formatDateTime(Date date) { | |||
| String text; | |||
| long dateTime = date.getTime(); | |||
| if (isSameDay(dateTime)) { | |||
| Calendar calendar = GregorianCalendar.getInstance(); | |||
| if (inOneMinute(dateTime, calendar.getTimeInMillis())) { | |||
| return "刚刚"; | |||
| } else if (inOneHour(dateTime, calendar.getTimeInMillis())) { | |||
| return String.format("%d分钟之前", Math.abs(dateTime - calendar.getTimeInMillis()) / 60000); | |||
| } else { | |||
| calendar.setTime(date); | |||
| text = "HH:mm"; | |||
| } | |||
| } else if (isYesterday(dateTime)) { | |||
| text = "昨天 HH:mm"; | |||
| } else if (isSameYear(dateTime)) { | |||
| text = "M-d HH:mm"; | |||
| } else { | |||
| text = "yyyy-M-d HH:mm"; | |||
| } | |||
| // 注意,如果使用android.text.format.DateFormat这个工具类,在API 17之前它只支持adEhkMmszy | |||
| return new SimpleDateFormat(text, Locale.CHINA).format(date); | |||
| } | |||
| /** | |||
| * 时间间隔是否在1min内 | |||
| * | |||
| * @param time1 毫秒 | |||
| * @param time2 毫秒 | |||
| * @return | |||
| */ | |||
| private static boolean inOneMinute(long time1, long time2) { | |||
| return Math.abs(time1 - time2) < 60000; | |||
| } | |||
| /** | |||
| * 时间间隔是否在1h内 | |||
| * | |||
| * @param time1 毫秒 | |||
| * @param time2 毫秒 | |||
| * @return | |||
| */ | |||
| private static boolean inOneHour(long time1, long time2) { | |||
| return Math.abs(time1 - time2) < 3600000; | |||
| } | |||
| /** | |||
| * 是否是同一天 | |||
| * | |||
| * @param time 毫秒 | |||
| * @return | |||
| */ | |||
| private static boolean isSameDay(long time) { | |||
| long startTime = floorDay(Calendar.getInstance()).getTimeInMillis(); | |||
| long endTime = ceilDay(Calendar.getInstance()).getTimeInMillis(); | |||
| return time > startTime && time < endTime; | |||
| } | |||
| /** | |||
| * 是否是昨天 | |||
| * | |||
| * @param time 毫秒 | |||
| * @return | |||
| */ | |||
| private static boolean isYesterday(long time) { | |||
| Calendar startCal; | |||
| startCal = floorDay(Calendar.getInstance()); | |||
| startCal.add(Calendar.DAY_OF_MONTH, -1); | |||
| long startTime = startCal.getTimeInMillis(); | |||
| Calendar endCal; | |||
| endCal = ceilDay(Calendar.getInstance()); | |||
| endCal.add(Calendar.DAY_OF_MONTH, -1); | |||
| long endTime = endCal.getTimeInMillis(); | |||
| return time > startTime && time < endTime; | |||
| } | |||
| /** | |||
| * 是否是同一年 | |||
| * | |||
| * @param time 毫秒 | |||
| * @return | |||
| */ | |||
| private static boolean isSameYear(long time) { | |||
| Calendar startCal; | |||
| startCal = floorDay(Calendar.getInstance()); | |||
| startCal.set(Calendar.MONTH, Calendar.JANUARY); | |||
| startCal.set(Calendar.DAY_OF_MONTH, 1); | |||
| return time >= startCal.getTimeInMillis(); | |||
| } | |||
| private static Calendar floorDay(Calendar startCal) { | |||
| startCal.set(Calendar.HOUR_OF_DAY, 0); | |||
| startCal.set(Calendar.MINUTE, 0); | |||
| startCal.set(Calendar.SECOND, 0); | |||
| startCal.set(Calendar.MILLISECOND, 0); | |||
| return startCal; | |||
| } | |||
| private static Calendar ceilDay(Calendar endCal) { | |||
| endCal.set(Calendar.HOUR_OF_DAY, 23); | |||
| endCal.set(Calendar.MINUTE, 59); | |||
| endCal.set(Calendar.SECOND, 59); | |||
| endCal.set(Calendar.MILLISECOND, 999); | |||
| return endCal; | |||
| } | |||
| } | |||
| @ -0,0 +1,144 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.os.Build; | |||
| import android.os.Environment; | |||
| import android.util.Log; | |||
| import java.io.File; | |||
| public class EmulatorUtils { | |||
| private static final String TAG = "EmulatorDetector"; | |||
| private static int rating = -1; | |||
| /** | |||
| * Detects if app is currenly running on emulator, or real device. | |||
| * @return true for emulator, false for real devices | |||
| */ | |||
| public static boolean isEmulator() { | |||
| int newRating = 0; | |||
| if(rating < 0) { | |||
| if (Build.PRODUCT.contains("sdk") || | |||
| Build.PRODUCT.contains("Andy") || | |||
| Build.PRODUCT.contains("ttVM_Hdragon") || | |||
| Build.PRODUCT.contains("google_sdk") || | |||
| Build.PRODUCT.contains("Droid4X") || | |||
| Build.PRODUCT.contains("nox") || | |||
| Build.PRODUCT.contains("sdk_x86") || | |||
| Build.PRODUCT.contains("sdk_google") || | |||
| Build.PRODUCT.contains("vbox86p")) { | |||
| newRating++; | |||
| } | |||
| if (Build.MANUFACTURER.equals("unknown") || | |||
| Build.MANUFACTURER.equals("Genymotion") || | |||
| Build.MANUFACTURER.contains("Andy") || | |||
| Build.MANUFACTURER.contains("MIT") || | |||
| Build.MANUFACTURER.contains("nox") || | |||
| Build.MANUFACTURER.contains("TiantianVM")){ | |||
| newRating++; | |||
| } | |||
| if (Build.BRAND.equals("generic") || | |||
| Build.BRAND.equals("generic_x86") || | |||
| Build.BRAND.equals("TTVM") || | |||
| Build.BRAND.contains("Andy")) { | |||
| newRating++; | |||
| } | |||
| if (Build.DEVICE.contains("generic") || | |||
| Build.DEVICE.contains("generic_x86") || | |||
| Build.DEVICE.contains("Andy") || | |||
| Build.DEVICE.contains("ttVM_Hdragon") || | |||
| Build.DEVICE.contains("Droid4X") || | |||
| Build.DEVICE.contains("nox") || | |||
| Build.DEVICE.contains("generic_x86_64") || | |||
| Build.DEVICE.contains("vbox86p")) { | |||
| newRating++; | |||
| } | |||
| if (Build.MODEL.equals("sdk") || | |||
| Build.MODEL.equals("google_sdk") || | |||
| Build.MODEL.contains("Droid4X") || | |||
| Build.MODEL.contains("TiantianVM") || | |||
| Build.MODEL.contains("Andy") || | |||
| Build.MODEL.equals("Android SDK built for x86_64") || | |||
| Build.MODEL.equals("Android SDK built for x86")) { | |||
| newRating++; | |||
| } | |||
| if (Build.HARDWARE.equals("goldfish") || | |||
| Build.HARDWARE.equals("vbox86") || | |||
| Build.HARDWARE.contains("nox") || | |||
| Build.HARDWARE.contains("ttVM_x86")) { | |||
| newRating++; | |||
| } | |||
| if (Build.FINGERPRINT.contains("generic/sdk/generic") || | |||
| Build.FINGERPRINT.contains("generic_x86/sdk_x86/generic_x86") || | |||
| Build.FINGERPRINT.contains("Andy") || | |||
| Build.FINGERPRINT.contains("ttVM_Hdragon") || | |||
| Build.FINGERPRINT.contains("generic_x86_64") || | |||
| Build.FINGERPRINT.contains("generic/google_sdk/generic") || | |||
| Build.FINGERPRINT.contains("vbox86p") || | |||
| Build.FINGERPRINT.contains("generic/vbox86p/vbox86p")) { | |||
| newRating++; | |||
| } | |||
| try { | |||
| String opengl = android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER); | |||
| if (opengl != null){ | |||
| if( opengl.contains("Bluestacks") || | |||
| opengl.contains("Translator") | |||
| ) | |||
| newRating += 10; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| try { | |||
| File sharedFolder = new File(Environment | |||
| .getExternalStorageDirectory().toString() | |||
| + File.separatorChar | |||
| + "windows" | |||
| + File.separatorChar | |||
| + "BstSharedFolder"); | |||
| if (sharedFolder.exists()) { | |||
| newRating += 10; | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| rating = newRating; | |||
| } | |||
| return rating > 3; | |||
| } | |||
| /** | |||
| * Returns string with human-readable listing of Build.* parameters used in {@link #isEmulator()} method. | |||
| * @return all involved Build.* parameters and its values | |||
| */ | |||
| public static String getDeviceListing() { | |||
| return "Build.PRODUCT: " + Build.PRODUCT + "\n" + | |||
| "Build.MANUFACTURER: " + Build.MANUFACTURER + "\n" + | |||
| "Build.BRAND: " + Build.BRAND + "\n" + | |||
| "Build.DEVICE: " + Build.DEVICE + "\n" + | |||
| "Build.MODEL: " + Build.MODEL + "\n" + | |||
| "Build.HARDWARE: " + Build.HARDWARE + "\n" + | |||
| "Build.FINGERPRINT: " + Build.FINGERPRINT + "\n" + | |||
| "Build.TAGS: " + android.os.Build.TAGS + "\n" + | |||
| "GL_RENDERER: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_RENDERER) + "\n" + | |||
| "GL_VENDOR: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_VENDOR) + "\n" + | |||
| "GL_VERSION: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_VERSION) + "\n" + | |||
| "GL_EXTENSIONS: " +android.opengl.GLES20.glGetString(android.opengl.GLES20.GL_EXTENSIONS) + "\n"; | |||
| } | |||
| /** | |||
| * Prints all Build.* parameters used in {@link #isEmulator()} method to logcat. | |||
| */ | |||
| public static void logcat() { | |||
| Log.d(TAG, getDeviceListing()); | |||
| } | |||
| } | |||
| @ -0,0 +1,368 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.os.Environment; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import com.handset.serialportsensor.bean.Sensor; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import org.apache.poi.hssf.usermodel.HSSFDateUtil; | |||
| import org.apache.poi.ss.usermodel.Cell; | |||
| import org.apache.poi.ss.usermodel.CellValue; | |||
| import org.apache.poi.ss.usermodel.FormulaEvaluator; | |||
| import org.apache.poi.ss.usermodel.Row; | |||
| import org.apache.poi.ss.usermodel.Workbook; | |||
| import org.apache.poi.ss.util.WorkbookUtil; | |||
| import org.apache.poi.xssf.usermodel.XSSFRow; | |||
| import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import java.util.List; | |||
| import static com.handset.serialportsensor.utils.DateStyle.YYYY_MM_DD_HH_MM_SS; | |||
| /** | |||
| * Created by zy on 2019/3/4. | |||
| */ | |||
| public class ExcelMa { | |||
| private final static String TAG = "ExcelMa"; | |||
| public static String getSavePath() { | |||
| String path = Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; | |||
| File dir = new File(path); | |||
| if (!dir.exists()) { | |||
| dir.mkdirs(); | |||
| } | |||
| return path; | |||
| } | |||
| public static File getSavePathFile() { | |||
| String path = Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; | |||
| File dir = new File(path); | |||
| if (!dir.exists()) { | |||
| dir.mkdirs(); | |||
| } | |||
| return dir; | |||
| } | |||
| public void createExcel() { | |||
| String name = getSavePath() + "workbook.xlsx"; | |||
| Workbook wb = new XSSFWorkbook(); | |||
| FileOutputStream fileOut = null; | |||
| try { | |||
| fileOut = new FileOutputStream(name); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| try { | |||
| wb.write(fileOut); | |||
| fileOut.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public void stopExport() { | |||
| exportStatus = false; | |||
| } | |||
| public void write(List<TestRecordsTotal> testRecordsTotals, PersistHelper.ExportCallback exportCallback, String timePerfix) { | |||
| exportStatus = true; | |||
| int counts = testRecordsTotals.size(); | |||
| int remain = counts; | |||
| for (int i = 0; i < counts; i++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| remain = counts - i; | |||
| exportCallback.exportProgress(counts, remain); | |||
| write(testRecordsTotals.get(i), timePerfix); | |||
| remain = counts - i - 1; | |||
| exportCallback.exportProgress(counts, remain); | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| } | |||
| exportCallback.finish(counts, remain); | |||
| } | |||
| public void write(TestRecordsTotal t, Sensor s, String tiems) { | |||
| File cacheDir = getSavePathFile(); | |||
| String sheetNama = t.sensor_id + "(" + tiems + ")"; | |||
| String outFileName = "检测结果(" + tiems + ").xlsx"; | |||
| File outFile = new File(cacheDir, outFileName); | |||
| InputStream stream = null; | |||
| try { | |||
| stream = new FileInputStream(outFile); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| XSSFWorkbook workbook = null; | |||
| try { | |||
| if (stream != null) { | |||
| workbook = new XSSFWorkbook(stream); | |||
| } | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| if (workbook == null) { | |||
| workbook = new XSSFWorkbook(); | |||
| Log.d(TAG, "write [t, s]:" + "create workbook"); | |||
| } | |||
| XSSFSheet sheet = workbook.getSheet(sheetNama); | |||
| if (sheet == null) { | |||
| sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(sheetNama)); | |||
| Log.d(TAG, "write [t, s]:" + "create sheet" + sheetNama); | |||
| } | |||
| int rows = sheet.getPhysicalNumberOfRows(); | |||
| Log.d(TAG, "write [t, s]rows:" + rows); | |||
| if (rows == 0) { | |||
| XSSFRow row = sheet.createRow(0); | |||
| row.createCell(0).setCellValue("采样时间戳"); | |||
| row.createCell(1).setCellValue("高精度温度(℃)温度"); | |||
| row.createCell(2).setCellValue("高精度湿度(%RH)"); | |||
| row.createCell(3).setCellValue("高精度内压(kPa)"); | |||
| row.createCell(4).setCellValue("高精度外压(kPa)"); | |||
| row.createCell(5).setCellValue("差压(kPa"); | |||
| row.createCell(6).setCellValue("20℃湿度(%RH)"); | |||
| row.createCell(7).setCellValue("20℃压力(kPa)"); | |||
| row.createCell(8).setCellValue("传感器编号"); | |||
| row.createCell(9).setCellValue("弹型"); | |||
| row.createCell(10).setCellValue("弹号"); | |||
| row.createCell(11).setCellValue("筒号"); | |||
| row.createCell(12).setCellValue("弹筒使用次数"); | |||
| row.createCell(13).setCellValue("波特率"); | |||
| rows++; | |||
| } | |||
| XSSFRow row = sheet.createRow(rows); | |||
| row.createCell(0).setCellValue(DateUtils.formatMilliesTimestamp(t.end_time, YYYY_MM_DD_HH_MM_SS)); | |||
| row.createCell(1).setCellValue(t.temp); | |||
| row.createCell(2).setCellValue(t.Hum); | |||
| row.createCell(3).setCellValue(t.pressurein); | |||
| row.createCell(4).setCellValue(t.pressureout); | |||
| row.createCell(5).setCellValue(t.pressure_yacha); | |||
| row.createCell(6).setCellValue(t.Hum20); | |||
| row.createCell(7).setCellValue(t.pressurein20); | |||
| row.createCell(8).setCellValue(t.sensor_id); | |||
| row.createCell(9).setCellValue(s.egg_type); | |||
| row.createCell(10).setCellValue(s.egg_id); | |||
| row.createCell(11).setCellValue(s.tupe_id); | |||
| row.createCell(12).setCellValue(t.tupe_use_times); | |||
| row.createCell(13).setCellValue(t.botelv); | |||
| FileOutputStream fileOut = null; | |||
| try { | |||
| fileOut = new FileOutputStream(outFile); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| try { | |||
| workbook.write(fileOut); | |||
| fileOut.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public void write(TestRecordsTotal t, String timePerfix) { | |||
| List<Sensor> s = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, "sensor_id = " + t.sensor_id + ""); | |||
| if (s == null || s.size() == 0) { | |||
| Log.e(TAG, "write [t]:" + "save test record failed, no sensor id info" + t.sensor_id + ""); | |||
| return; | |||
| } | |||
| write(t, s.get(0), timePerfix); | |||
| } | |||
| protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) { | |||
| String value = ""; | |||
| try { | |||
| Cell cell = row.getCell(c); | |||
| CellValue cellValue = formulaEvaluator.evaluate(cell); | |||
| switch (cellValue.getCellType()) { | |||
| case Cell.CELL_TYPE_BOOLEAN: | |||
| value = "" + cellValue.getBooleanValue(); | |||
| break; | |||
| case Cell.CELL_TYPE_NUMERIC: | |||
| double numericValue = cellValue.getNumberValue(); | |||
| if (HSSFDateUtil.isCellDateFormatted(cell)) { | |||
| double date = cellValue.getNumberValue(); | |||
| SimpleDateFormat formatter = | |||
| new SimpleDateFormat("dd/MM/yy"); | |||
| value = formatter.format(HSSFDateUtil.getJavaDate(date)); | |||
| } else { | |||
| value = "" + numericValue; | |||
| } | |||
| break; | |||
| case Cell.CELL_TYPE_STRING: | |||
| value = "" + cellValue.getStringValue(); | |||
| break; | |||
| default: | |||
| } | |||
| } catch (NullPointerException e) { | |||
| /* proper error handling should be here */ | |||
| e.printStackTrace(); | |||
| } | |||
| return value; | |||
| } | |||
| public void onWriteClick(TestRecordsTotal testRecordsTotal) { | |||
| XSSFWorkbook workbook = new XSSFWorkbook(); | |||
| XSSFSheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("mysheet")); | |||
| for (int i = 0; i < 10; i++) { | |||
| Row row = sheet.createRow(i); | |||
| Cell cell = row.createCell(0); | |||
| cell.setCellValue(i); | |||
| } | |||
| String outFileName = "filetoshare.xlsx"; | |||
| try { | |||
| File cacheDir = getSavePathFile(); | |||
| File outFile = new File(cacheDir, outFileName); | |||
| OutputStream outputStream = new FileOutputStream(outFile.getAbsolutePath()); | |||
| workbook.write(outputStream); | |||
| outputStream.flush(); | |||
| outputStream.close(); | |||
| //share(outFileName, getApplicationContext()); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| //导出线程的状态 | |||
| volatile boolean exportStatus = true; | |||
| public void onReadClick(File file, PersistHelper.ExportCallback exportCallback) { | |||
| exportStatus = true; | |||
| PersistHelper.resetDB(); | |||
| int dataItems = 0; | |||
| int remain = dataItems; | |||
| Log.d(TAG, "onReadClick [view]:"); | |||
| try { | |||
| InputStream stream = new FileInputStream(file); | |||
| XSSFWorkbook workbook = new XSSFWorkbook(stream); | |||
| int sheetsNums = workbook.getNumberOfSheets(); | |||
| Log.d(TAG, "onReadClick [file]sheetsNums:" + sheetsNums); | |||
| dataItems = 0; | |||
| for (int i = 0; i < sheetsNums; i++) { | |||
| dataItems += workbook.getSheetAt(i).getPhysicalNumberOfRows() - 1; | |||
| } | |||
| Log.d(TAG, "onReadClick [file]dataItems:" + dataItems); | |||
| remain = dataItems; | |||
| exportCallback.exportProgress(dataItems, remain); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| for (int i = 0; i < sheetsNums; i++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| Sensor s = new Sensor(); | |||
| XSSFSheet sheet = workbook.getSheetAt(i); | |||
| int rowsCount = sheet.getPhysicalNumberOfRows(); | |||
| FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); | |||
| for (int r = 1; r < rowsCount; r++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| Row row = sheet.getRow(r); | |||
| int cellsCount = row.getPhysicalNumberOfCells(); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| testRecordsTotal.id = PersistHelper.generateNextTestId(); | |||
| String et = getCellAsString(row, 0, formulaEvaluator); | |||
| //2019-03-05 14:52:42 | |||
| calendar.set( | |||
| Integer.parseInt(et.substring(0, 4)), | |||
| Integer.parseInt(et.substring(5, 7)) - 1, | |||
| Integer.parseInt(et.substring(8, 10)), | |||
| Integer.parseInt(et.substring(11, 13)), | |||
| Integer.parseInt(et.substring(14, 16)), | |||
| Integer.parseInt(et.substring(17, 19))); | |||
| String te = getCellAsString(row, 1, formulaEvaluator); | |||
| testRecordsTotal.temp = Float.parseFloat(te); | |||
| String hum = getCellAsString(row, 2, formulaEvaluator); | |||
| testRecordsTotal.Hum = Float.parseFloat(hum); | |||
| String neiya = getCellAsString(row, 3, formulaEvaluator); | |||
| testRecordsTotal.pressurein = Float.parseFloat(neiya); | |||
| String waiya = getCellAsString(row, 4, formulaEvaluator); | |||
| testRecordsTotal.pressureout = Float.parseFloat(waiya); | |||
| String yacha = getCellAsString(row, 5, formulaEvaluator); | |||
| testRecordsTotal.pressure_yacha = Float.parseFloat(yacha); | |||
| String shidu20 = getCellAsString(row, 6, formulaEvaluator); | |||
| testRecordsTotal.Hum20 = Float.parseFloat(shidu20); | |||
| String yali20 = getCellAsString(row, 7, formulaEvaluator); | |||
| testRecordsTotal.pressurein20 = Float.parseFloat(yali20); | |||
| testRecordsTotal.end_time = calendar.getTimeInMillis(); | |||
| calendar.setTimeInMillis(testRecordsTotal.end_time); | |||
| testRecordsTotal.day_t = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; | |||
| String sensor_id = getCellAsString(row, 8, formulaEvaluator); | |||
| if (sensor_id.length() > 8) { | |||
| sensor_id = sensor_id.replace(".", "").substring(0, 8); | |||
| } | |||
| testRecordsTotal.sensor_id = Long.parseLong(sensor_id); | |||
| s.sensor_id = testRecordsTotal.sensor_id; | |||
| String danxing = getCellAsString(row, 9, formulaEvaluator); | |||
| s.egg_type = danxing; | |||
| String danhao = getCellAsString(row, 10, formulaEvaluator); | |||
| s.egg_id = danhao; | |||
| String tonghao = getCellAsString(row, 11, formulaEvaluator); | |||
| s.tupe_id = tonghao; | |||
| String tupeUsetimes = getCellAsString(row, 12, formulaEvaluator); | |||
| if (!TextUtils.isEmpty(tupeUsetimes)) { | |||
| if (tupeUsetimes.endsWith(".0")) { | |||
| tupeUsetimes = tupeUsetimes.replace(".0", ""); | |||
| } | |||
| s.tv_tupe_use_times = tupeUsetimes; | |||
| testRecordsTotal.tupe_use_times = tupeUsetimes; | |||
| } | |||
| String botelv = getCellAsString(row, 13, formulaEvaluator); | |||
| testRecordsTotal.botelv = botelv; | |||
| if (KJDB.getDefaultInstance().findById(testRecordsTotal.id, TestRecordsTotal.class) != null) { | |||
| KJDB.getDefaultInstance().update(testRecordsTotal); | |||
| } else { | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| } | |||
| remain--; | |||
| exportCallback.exportProgress(dataItems, remain); | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| } | |||
| if (KJDB.getDefaultInstance().findById(s.id, Sensor.class) != null) { | |||
| KJDB.getDefaultInstance().update(s); | |||
| } else { | |||
| KJDB.getDefaultInstance().save(s); | |||
| } | |||
| } | |||
| stream.close(); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } finally { | |||
| } | |||
| exportCallback.finish(dataItems, remain); | |||
| } | |||
| } | |||
| @ -0,0 +1,364 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.os.Environment; | |||
| import android.text.TextUtils; | |||
| import android.util.Log; | |||
| import com.handset.serialportsensor.bean.Sensor; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import org.apache.poi.hssf.usermodel.HSSFDateUtil; | |||
| import org.apache.poi.ss.usermodel.Cell; | |||
| import org.apache.poi.ss.usermodel.CellValue; | |||
| import org.apache.poi.ss.usermodel.FormulaEvaluator; | |||
| import org.apache.poi.ss.usermodel.Row; | |||
| import org.apache.poi.ss.usermodel.Workbook; | |||
| import org.apache.poi.ss.util.WorkbookUtil; | |||
| import org.apache.poi.xssf.usermodel.XSSFRow; | |||
| import org.apache.poi.xssf.usermodel.XSSFSheet; | |||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.io.File; | |||
| import java.io.FileInputStream; | |||
| import java.io.FileNotFoundException; | |||
| import java.io.FileOutputStream; | |||
| import java.io.IOException; | |||
| import java.io.InputStream; | |||
| import java.io.OutputStream; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.Calendar; | |||
| import java.util.List; | |||
| /** | |||
| * Created by zy on 2019/3/4. | |||
| */ | |||
| public class ExcelUtils { | |||
| private final static String TAG = "ExcelMa"; | |||
| public static String getSavePath() { | |||
| String path = Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; | |||
| File dir = new File(path); | |||
| if (!dir.exists()) { | |||
| dir.mkdirs(); | |||
| } | |||
| return path; | |||
| } | |||
| public static File getSavePathFile() { | |||
| String path = Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "export" + File.separator; | |||
| File dir = new File(path); | |||
| if (!dir.exists()) { | |||
| dir.mkdirs(); | |||
| } | |||
| return dir; | |||
| } | |||
| public void createExcel() { | |||
| String name = getSavePath() + "workbook.xlsx"; | |||
| Workbook wb = new XSSFWorkbook(); | |||
| FileOutputStream fileOut = null; | |||
| try { | |||
| fileOut = new FileOutputStream(name); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| try { | |||
| wb.write(fileOut); | |||
| fileOut.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public void stopExport() { | |||
| exportStatus = false; | |||
| } | |||
| public void write(List<TestRecordsTotal> testRecordsTotals, PersistHelper.ExportCallback exportCallback, String timePerfix) { | |||
| exportStatus = true; | |||
| int counts = testRecordsTotals.size(); | |||
| int remain = counts; | |||
| for (int i = 0; i < counts; i++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| remain = counts - i; | |||
| exportCallback.exportProgress(counts, remain); | |||
| write(testRecordsTotals.get(i), timePerfix); | |||
| remain = counts - i - 1; | |||
| exportCallback.exportProgress(counts, remain); | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| } | |||
| exportCallback.finish(counts, remain); | |||
| } | |||
| public void write(TestRecordsTotal t, Sensor s, String tiems) { | |||
| File cacheDir = getSavePathFile(); | |||
| String sheetNama = t.sensor_id + "(" + tiems + ")"; | |||
| String outFileName = "检测结果(" + tiems + ").xlsx"; | |||
| File outFile = new File(cacheDir, outFileName); | |||
| InputStream stream = null; | |||
| try { | |||
| stream = new FileInputStream(outFile); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| XSSFWorkbook workbook = null; | |||
| try { | |||
| if (stream != null) { | |||
| workbook = new XSSFWorkbook(stream); | |||
| } | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| if (workbook == null) { | |||
| workbook = new XSSFWorkbook(); | |||
| Log.d(TAG, "write [t, s]:" + "create workbook"); | |||
| } | |||
| XSSFSheet sheet = workbook.getSheet(sheetNama); | |||
| if (sheet == null) { | |||
| sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(sheetNama)); | |||
| Log.d(TAG, "write [t, s]:" + "create sheet" + sheetNama); | |||
| } | |||
| int rows = sheet.getPhysicalNumberOfRows(); | |||
| Log.d(TAG, "write [t, s]rows:" + rows); | |||
| if (rows == 0) { | |||
| XSSFRow row = sheet.createRow(0); | |||
| row.createCell(0).setCellValue("采样时间戳"); | |||
| row.createCell(1).setCellValue("高精度温度(℃)温度"); | |||
| row.createCell(2).setCellValue("高精度湿度(%RH)"); | |||
| row.createCell(3).setCellValue("高精度内压(kPa)"); | |||
| row.createCell(4).setCellValue("高精度外压(kPa)"); | |||
| row.createCell(5).setCellValue("差压(kPa"); | |||
| row.createCell(6).setCellValue("20℃湿度(%RH)"); | |||
| row.createCell(7).setCellValue("20℃压力(kPa)"); | |||
| row.createCell(8).setCellValue("传感器编号"); | |||
| row.createCell(9).setCellValue("弹型"); | |||
| row.createCell(10).setCellValue("弹号"); | |||
| row.createCell(11).setCellValue("筒号"); | |||
| row.createCell(12).setCellValue("弹筒使用次数"); | |||
| row.createCell(13).setCellValue("波特率"); | |||
| rows++; | |||
| } | |||
| XSSFRow row = sheet.createRow(rows); | |||
| row.createCell(0).setCellValue(DateUtils.formatMilliesTimestamp(t.end_time, "yyyy-MM-dd HH:mm:ss")); | |||
| row.createCell(1).setCellValue(t.temp); | |||
| row.createCell(2).setCellValue(t.Hum); | |||
| row.createCell(3).setCellValue(t.pressurein); | |||
| row.createCell(4).setCellValue(t.pressureout); | |||
| row.createCell(5).setCellValue(t.pressure_yacha); | |||
| row.createCell(6).setCellValue(t.Hum20); | |||
| row.createCell(7).setCellValue(t.pressurein20); | |||
| row.createCell(8).setCellValue(t.sensor_id); | |||
| row.createCell(9).setCellValue(s.egg_type); | |||
| row.createCell(10).setCellValue(s.egg_id); | |||
| row.createCell(11).setCellValue(s.tupe_id); | |||
| row.createCell(12).setCellValue(t.tupe_use_times); | |||
| row.createCell(13).setCellValue(t.botelv); | |||
| FileOutputStream fileOut = null; | |||
| try { | |||
| fileOut = new FileOutputStream(outFile); | |||
| } catch (FileNotFoundException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| try { | |||
| workbook.write(fileOut); | |||
| fileOut.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public void write(TestRecordsTotal t, String timePerfix) { | |||
| List<Sensor> s = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, "sensor_id = " + t.sensor_id + ""); | |||
| if (s == null || s.size() == 0) { | |||
| Log.e(TAG, "write [t]:" + "save test record failed, no sensor id info" + t.sensor_id + ""); | |||
| return; | |||
| } | |||
| write(t, s.get(0), timePerfix); | |||
| } | |||
| protected String getCellAsString(Row row, int c, FormulaEvaluator formulaEvaluator) { | |||
| String value = ""; | |||
| try { | |||
| Cell cell = row.getCell(c); | |||
| CellValue cellValue = formulaEvaluator.evaluate(cell); | |||
| switch (cellValue.getCellType()) { | |||
| case Cell.CELL_TYPE_BOOLEAN: | |||
| value = "" + cellValue.getBooleanValue(); | |||
| break; | |||
| case Cell.CELL_TYPE_NUMERIC: | |||
| double numericValue = cellValue.getNumberValue(); | |||
| if (HSSFDateUtil.isCellDateFormatted(cell)) { | |||
| double date = cellValue.getNumberValue(); | |||
| SimpleDateFormat formatter = | |||
| new SimpleDateFormat("dd/MM/yy"); | |||
| value = formatter.format(HSSFDateUtil.getJavaDate(date)); | |||
| } else { | |||
| value = "" + numericValue; | |||
| } | |||
| break; | |||
| case Cell.CELL_TYPE_STRING: | |||
| value = "" + cellValue.getStringValue(); | |||
| break; | |||
| default: | |||
| } | |||
| } catch (NullPointerException e) { | |||
| /* proper error handling should be here */ | |||
| e.printStackTrace(); | |||
| } | |||
| return value; | |||
| } | |||
| public void onWriteClick(TestRecordsTotal testRecordsTotal) { | |||
| XSSFWorkbook workbook = new XSSFWorkbook(); | |||
| XSSFSheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName("mysheet")); | |||
| for (int i = 0; i < 10; i++) { | |||
| Row row = sheet.createRow(i); | |||
| Cell cell = row.createCell(0); | |||
| cell.setCellValue(i); | |||
| } | |||
| String outFileName = "filetoshare.xlsx"; | |||
| try { | |||
| File cacheDir = getSavePathFile(); | |||
| File outFile = new File(cacheDir, outFileName); | |||
| OutputStream outputStream = new FileOutputStream(outFile.getAbsolutePath()); | |||
| workbook.write(outputStream); | |||
| outputStream.flush(); | |||
| outputStream.close(); | |||
| //share(outFileName, getApplicationContext()); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| //导出线程的状态 | |||
| volatile boolean exportStatus = true; | |||
| public void onReadClick(File file, PersistHelper.ExportCallback exportCallback) { | |||
| exportStatus = true; | |||
| PersistHelper.resetDB(); | |||
| int dataItems = 0; | |||
| int remain = dataItems; | |||
| Log.d(TAG, "onReadClick [view]:"); | |||
| try { | |||
| InputStream stream = new FileInputStream(file); | |||
| XSSFWorkbook workbook = new XSSFWorkbook(stream); | |||
| int sheetsNums = workbook.getNumberOfSheets(); | |||
| Log.d(TAG, "onReadClick [file]sheetsNums:" + sheetsNums); | |||
| dataItems = 0; | |||
| for (int i = 0; i < sheetsNums; i++) { | |||
| dataItems += workbook.getSheetAt(i).getPhysicalNumberOfRows() - 1; | |||
| } | |||
| Log.d(TAG, "onReadClick [file]dataItems:" + dataItems); | |||
| remain = dataItems; | |||
| exportCallback.exportProgress(dataItems, remain); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| for (int i = 0; i < sheetsNums; i++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| Sensor s = new Sensor(); | |||
| XSSFSheet sheet = workbook.getSheetAt(i); | |||
| int rowsCount = sheet.getPhysicalNumberOfRows(); | |||
| FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator(); | |||
| for (int r = 1; r < rowsCount; r++) { | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| Row row = sheet.getRow(r); | |||
| int cellsCount = row.getPhysicalNumberOfCells(); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| testRecordsTotal.id = PersistHelper.generateNextTestId(); | |||
| String et = getCellAsString(row, 0, formulaEvaluator); | |||
| //2019-03-05 14:52:42 | |||
| calendar.set( | |||
| Integer.parseInt(et.substring(0, 4)), | |||
| Integer.parseInt(et.substring(5, 7)) - 1, | |||
| Integer.parseInt(et.substring(8, 10)), | |||
| Integer.parseInt(et.substring(11, 13)), | |||
| Integer.parseInt(et.substring(14, 16)), | |||
| Integer.parseInt(et.substring(17, 19))); | |||
| String te = getCellAsString(row, 1, formulaEvaluator); | |||
| testRecordsTotal.temp = Float.parseFloat(te); | |||
| String hum = getCellAsString(row, 2, formulaEvaluator); | |||
| testRecordsTotal.Hum = Float.parseFloat(hum); | |||
| String neiya = getCellAsString(row, 3, formulaEvaluator); | |||
| testRecordsTotal.pressurein = Float.parseFloat(neiya); | |||
| String waiya = getCellAsString(row, 4, formulaEvaluator); | |||
| testRecordsTotal.pressureout = Float.parseFloat(waiya); | |||
| String yacha = getCellAsString(row, 5, formulaEvaluator); | |||
| testRecordsTotal.pressure_yacha = Float.parseFloat(yacha); | |||
| String shidu20 = getCellAsString(row, 6, formulaEvaluator); | |||
| testRecordsTotal.Hum20 = Float.parseFloat(shidu20); | |||
| String yali20 = getCellAsString(row, 7, formulaEvaluator); | |||
| testRecordsTotal.pressurein20 = Float.parseFloat(yali20); | |||
| testRecordsTotal.end_time = calendar.getTimeInMillis(); | |||
| calendar.setTimeInMillis(testRecordsTotal.end_time); | |||
| testRecordsTotal.day_t = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; | |||
| String sensor_id = getCellAsString(row, 8, formulaEvaluator); | |||
| if (sensor_id.length() > 8) { | |||
| sensor_id = sensor_id.replace(".", "").substring(0, 8); | |||
| } | |||
| testRecordsTotal.sensor_id = Long.parseLong(sensor_id); | |||
| s.sensor_id = testRecordsTotal.sensor_id; | |||
| String danxing = getCellAsString(row, 9, formulaEvaluator); | |||
| s.egg_type = danxing; | |||
| String danhao = getCellAsString(row, 10, formulaEvaluator); | |||
| s.egg_id = danhao; | |||
| String tonghao = getCellAsString(row, 11, formulaEvaluator); | |||
| s.tupe_id = tonghao; | |||
| String tupeUsetimes = getCellAsString(row, 12, formulaEvaluator); | |||
| if (!TextUtils.isEmpty(tupeUsetimes)) { | |||
| if (tupeUsetimes.endsWith(".0")) { | |||
| tupeUsetimes = tupeUsetimes.replace(".0", ""); | |||
| } | |||
| s.tv_tupe_use_times = tupeUsetimes; | |||
| testRecordsTotal.tupe_use_times = tupeUsetimes; | |||
| } | |||
| String botelv = getCellAsString(row, 13, formulaEvaluator); | |||
| testRecordsTotal.botelv = botelv; | |||
| if (KJDB.getDefaultInstance().findById(testRecordsTotal.id, TestRecordsTotal.class) != null) { | |||
| KJDB.getDefaultInstance().update(testRecordsTotal); | |||
| } else { | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| } | |||
| remain--; | |||
| exportCallback.exportProgress(dataItems, remain); | |||
| if (!exportStatus) { | |||
| break; | |||
| } | |||
| } | |||
| if (KJDB.getDefaultInstance().findById(s.id, Sensor.class) != null) { | |||
| KJDB.getDefaultInstance().update(s); | |||
| } else { | |||
| KJDB.getDefaultInstance().save(s); | |||
| } | |||
| } | |||
| stream.close(); | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } finally { | |||
| } | |||
| exportCallback.finish(dataItems, remain); | |||
| } | |||
| } | |||
| @ -0,0 +1,377 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| import android.util.Log; | |||
| import android.util.SparseArray; | |||
| import com.handset.serialportsensor.bean.Sensor; | |||
| import com.handset.serialportsensor.bean.TestRecordsTotal; | |||
| import org.kymjs.kjframe.KJDB; | |||
| import java.text.DecimalFormat; | |||
| import java.util.Calendar; | |||
| import java.util.List; | |||
| /** | |||
| * Created by zy on 2019/2/24. | |||
| */ | |||
| public class PersistHelper { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private static Context sContext; | |||
| private static Sensor mSensor = null; | |||
| private static ExcelUtils excelUtils; | |||
| public static void init(Context context) { | |||
| sContext = context; | |||
| excelUtils = new ExcelUtils(); | |||
| } | |||
| public static void generateSimulateData() { | |||
| KJDB.getDefaultInstance().deleteByWhere(Sensor.class, "1=1"); | |||
| KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "1=1"); | |||
| initSensor(); | |||
| } | |||
| private static void initSensor() { | |||
| Sensor sensor = new Sensor(); | |||
| sensor.id = 1; | |||
| sensor.egg_id = "EGG11234"; | |||
| sensor.sensor_id = 19011111; | |||
| sensor.egg_type = "EGGA1234"; | |||
| sensor.tupe_id = "TUPEA1234"; | |||
| KJDB.getDefaultInstance().save(sensor); | |||
| sensor.id = 2; | |||
| sensor.egg_id = "EGG21234"; | |||
| sensor.sensor_id = 19011112; | |||
| sensor.egg_type = "EGGB1234"; | |||
| sensor.tupe_id = "TUPEB1234"; | |||
| KJDB.getDefaultInstance().save(sensor); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| long a = 315360000000L; | |||
| testRecordsTotal.end_time = System.currentTimeMillis() - a; | |||
| testRecordsTotal.Hum = 80; | |||
| testRecordsTotal.sensor_id = 19011111; | |||
| testRecordsTotal.pressure_yacha = 100; | |||
| testRecordsTotal.pressurein = 90; | |||
| testRecordsTotal.pressureout = 120; | |||
| testRecordsTotal.temp = 50; | |||
| testRecordsTotal.Hum20 = 90; | |||
| testRecordsTotal.pressurein20 = 20; | |||
| testRecordsTotal.tupe_use_times = "10"; | |||
| int i = 1; | |||
| Calendar c = Calendar.getInstance(); | |||
| for (; i < 5000; i++) { | |||
| testRecordsTotal.id = i; | |||
| testRecordsTotal.end_time += 24 * 3600000; | |||
| c.setTimeInMillis(testRecordsTotal.end_time); | |||
| testRecordsTotal.day_t = c.get(Calendar.DAY_OF_YEAR) + c.get(Calendar.YEAR) * 1000; | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| if (i % 100 == 0) { | |||
| Log.d(logTag, "initSensor []:" + i); | |||
| } | |||
| } | |||
| testRecordsTotal.sensor_id = 19011112; | |||
| for (; i < 10000; i++) { | |||
| testRecordsTotal.id = i; | |||
| testRecordsTotal.end_time += 24 * 3600000; | |||
| c.setTimeInMillis(testRecordsTotal.end_time); | |||
| testRecordsTotal.day_t = c.get(Calendar.DAY_OF_YEAR) + c.get(Calendar.YEAR) * 1000; | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| if (i % 100 == 0) { | |||
| Log.d(logTag, "initSensor []:" + i); | |||
| } | |||
| } | |||
| } | |||
| public static void resetDB() { | |||
| KJDB.getDefaultInstance().deleteByWhere(Sensor.class, "1=1"); | |||
| KJDB.getDefaultInstance().deleteByWhere(TestRecordsTotal.class, "1=1"); | |||
| SPUtils.getInstance(sContext).put("current_test_id", -1l); | |||
| } | |||
| public static long generateNextTestId() { | |||
| long currentTestId = SPUtils.getInstance(sContext).get("current_test_id", -1L); | |||
| long newId = currentTestId == -1 || currentTestId >= 10000000 ? 1 : currentTestId + 1; | |||
| TestRecordsTotal old = KJDB.getDefaultInstance().findById(newId, TestRecordsTotal.class); | |||
| if (old != null) { | |||
| KJDB.getDefaultInstance().delete(old); | |||
| } | |||
| SPUtils.getInstance(sContext).put("current_test_id", newId); | |||
| return newId; | |||
| } | |||
| private static long NextTestIdCC() { | |||
| long currentTestId = SPUtils.getInstance(sContext).get("current_test_id", -1l); | |||
| long newId = currentTestId - 1; | |||
| if (newId == -1 || newId == 0 || currentTestId >= 10000000) { | |||
| newId = 0; | |||
| } | |||
| TestRecordsTotal old = KJDB.getDefaultInstance().findById(currentTestId, TestRecordsTotal.class); | |||
| if (old != null) { | |||
| KJDB.getDefaultInstance().delete(old); | |||
| } | |||
| SPUtils.getInstance(sContext).put("current_test_id", newId); | |||
| return newId; | |||
| } | |||
| /** | |||
| * 生成下一个保存数据的Id | |||
| * <p> | |||
| * 考虑到测试Id保存的的上线是1000 000,循环利用ID,超过后复写以前的数据 | |||
| */ | |||
| public static long generateNextTestId(int idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { | |||
| if (sContext == null) { | |||
| return -1; | |||
| } | |||
| long newId = generateNextTestId(); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| testRecordsTotal.id = newId; | |||
| testRecordsTotal.botelv = sbotelv; | |||
| Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| if (mSensor == null) { | |||
| mSensor = new Sensor(); | |||
| } | |||
| int[] values = ProtoUtils.getSensorNumber(idHigh1, idHigh2, idHigh3, idHigh4); | |||
| mSensor.sensor_id = values[1]; | |||
| return newId; | |||
| } | |||
| public static void genItem(int sensorId) { | |||
| if (sContext == null) { | |||
| return; | |||
| } | |||
| long newId = generateNextTestId(); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| testRecordsTotal.id = newId; | |||
| testRecordsTotal.botelv = sbotelv; | |||
| Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| if (mSensor == null) { | |||
| mSensor = new Sensor(); | |||
| } | |||
| mSensor.sensor_id = sensorId; | |||
| } | |||
| public static void genItem(int sensorId, String baudRate) { | |||
| if (sContext == null) { | |||
| return; | |||
| } | |||
| long newId = generateNextTestId(); | |||
| TestRecordsTotal testRecordsTotal = new TestRecordsTotal(); | |||
| testRecordsTotal.id = newId; | |||
| testRecordsTotal.botelv = baudRate; | |||
| Log.d(logTag, "generateNextTestId [idHigh1, idHigh2, idHigh3, idHigh4]:" + newId); | |||
| KJDB.getDefaultInstance().save(testRecordsTotal); | |||
| if (mSensor == null) { | |||
| mSensor = new Sensor(); | |||
| } | |||
| mSensor.sensor_id = sensorId; | |||
| } | |||
| static String sbotelv = "38400"; | |||
| public static void mateSuccess(String botelv) { | |||
| sbotelv = botelv; | |||
| } | |||
| public static long getCurrentTestId() { | |||
| if (sContext == null) { | |||
| return -1; | |||
| } | |||
| return SPUtils.getInstance(sContext).get("current_test_id", -1l); | |||
| } | |||
| public static TestRecordsTotal getCurrentTestRecordsTotal() { | |||
| if (sContext == null) { | |||
| return null; | |||
| } | |||
| long id = getCurrentTestId(); | |||
| if (id == -1) { | |||
| return null; | |||
| } | |||
| return KJDB.getDefaultInstance().findById(id, TestRecordsTotal.class); | |||
| } | |||
| public static void saveEggID(String eggNumber) { | |||
| /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); | |||
| testRecordsTotal.egg_id = eggNumber; | |||
| KJDB.getDefaultInstance().update(testRecordsTotal);*/ | |||
| mSensor.egg_id = eggNumber; | |||
| } | |||
| public static void saveEggType(String eggType) { | |||
| /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); | |||
| testRecordsTotal.egg_type = eggtype; | |||
| KJDB.getDefaultInstance().update(testRecordsTotal);*/ | |||
| mSensor.egg_type = eggType; | |||
| } | |||
| public static void saveConeNo(String coneNo) { | |||
| /*TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); | |||
| testRecordsTotal.tupe_id = coneNumber; | |||
| KJDB.getDefaultInstance().update(testRecordsTotal);*/ | |||
| mSensor.tupe_id = coneNo; | |||
| } | |||
| public static void saveConeUsedTimes(String usedTimes) { | |||
| TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); | |||
| testRecordsTotal.tupe_use_times = usedTimes; | |||
| mSensor.tv_tupe_use_times = usedTimes; | |||
| KJDB.getDefaultInstance().update(testRecordsTotal); | |||
| } | |||
| private static SparseArray<Item> sItemSparseArray = new SparseArray<>(); | |||
| public static void save(float value, int type) { | |||
| Item i = sItemSparseArray.get(type); | |||
| if (i != null) { | |||
| i.count++; | |||
| i.sum += value; | |||
| i.average = i.sum / i.count; | |||
| } else { | |||
| Item item = new Item(); | |||
| item.count = 1; | |||
| item.sum = value; | |||
| item.average = value; | |||
| sItemSparseArray.put(type, item); | |||
| } | |||
| } | |||
| public static class Item { | |||
| int count = 0; | |||
| float sum = 0; | |||
| float average = 0; | |||
| } | |||
| public static void endTest(boolean save) { | |||
| if (save) { | |||
| endTest(); | |||
| } else { | |||
| NextTestIdCC(); | |||
| //清楚所有单条记录 | |||
| sItemSparseArray.clear(); | |||
| sbotelv = ""; | |||
| } | |||
| } | |||
| /*结束本次测试*/ | |||
| public static void endTest() { | |||
| long id = getCurrentTestId(); | |||
| if (id < 0) { | |||
| return; | |||
| } | |||
| TestRecordsTotal testRecordsTotal = getCurrentTestRecordsTotal(); | |||
| if (testRecordsTotal == null) { | |||
| return; | |||
| } | |||
| /*温度*/ | |||
| float temp = -1000; | |||
| /*湿度*/ | |||
| float Hum = -1000; | |||
| /*内压*/ | |||
| float pressurein = -1000; | |||
| /*外压*/ | |||
| float pressureout = -1000; | |||
| /*压差*/ | |||
| float pressure_yacha = -1000; | |||
| /*湿度*/ | |||
| float Hum20 = -1000; | |||
| /*内压*/ | |||
| float pressurein20 = -1000; | |||
| Item iItem41 = sItemSparseArray.get(41); | |||
| if (iItem41 != null) { | |||
| temp = iItem41.average; | |||
| } | |||
| testRecordsTotal.temp = f(temp); | |||
| Item iItem42 = sItemSparseArray.get(42); | |||
| if (iItem42 != null) { | |||
| pressurein = iItem42.average; | |||
| } | |||
| testRecordsTotal.pressurein = f(pressurein); | |||
| Item iItem43 = sItemSparseArray.get(43); | |||
| if (iItem43 != null) { | |||
| Hum = iItem43.average; | |||
| } | |||
| testRecordsTotal.Hum = f(Hum); | |||
| Item iItem44 = sItemSparseArray.get(44); | |||
| if (iItem44 != null) { | |||
| pressureout = iItem44.average; | |||
| } | |||
| testRecordsTotal.pressureout = f(pressureout); | |||
| Item iItem45 = sItemSparseArray.get(45); | |||
| if (iItem45 != null) { | |||
| pressure_yacha = iItem45.average; | |||
| } | |||
| testRecordsTotal.pressure_yacha = f(pressure_yacha); | |||
| Item iItem46 = sItemSparseArray.get(46); | |||
| if (iItem46 != null) { | |||
| Hum20 = iItem46.average; | |||
| } | |||
| testRecordsTotal.Hum20 = f(Hum20); | |||
| Item iItem47 = sItemSparseArray.get(47); | |||
| if (iItem47 != null) { | |||
| pressurein20 = iItem47.average; | |||
| } | |||
| testRecordsTotal.pressurein20 = f(pressurein20); | |||
| testRecordsTotal.end_time = System.currentTimeMillis(); | |||
| Calendar calendar = Calendar.getInstance(); | |||
| calendar.setTimeInMillis(testRecordsTotal.end_time); | |||
| long startDatT = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000; | |||
| testRecordsTotal.day_t = startDatT; | |||
| List<Sensor> listSensor = KJDB.getDefaultInstance().findAllByWhere(Sensor.class, | |||
| "sensor_id=" + mSensor.sensor_id); | |||
| if (listSensor != null && listSensor.size() > 0) { | |||
| mSensor.id = listSensor.get(0).id; | |||
| KJDB.getDefaultInstance().update(mSensor); | |||
| } else { | |||
| KJDB.getDefaultInstance().save(mSensor); | |||
| } | |||
| testRecordsTotal.sensor_id = mSensor.sensor_id; | |||
| //更新execl信息 | |||
| //mExeclMa.write(testRecordsTotal); | |||
| testRecordsTotal.tagBackup = 0; | |||
| KJDB.getDefaultInstance().update(testRecordsTotal); | |||
| //清楚所有单条记录 | |||
| sItemSparseArray.clear(); | |||
| sbotelv = ""; | |||
| } | |||
| private static float f(float f) { | |||
| DecimalFormat df = new DecimalFormat("0.0"); | |||
| String pressure1 = df.format(f); | |||
| try { | |||
| Float ff = Float.parseFloat(pressure1); | |||
| return ff; | |||
| } catch (NumberFormatException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return f; | |||
| } | |||
| public interface ExportCallback { | |||
| void exportProgress(int counts, int remain); | |||
| void finish(int counts, int remain); | |||
| } | |||
| } | |||
| @ -0,0 +1,25 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| public class PixelUtils { | |||
| public static int px2sp(Context context, float pxValue) { | |||
| final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; | |||
| return (int) (pxValue / fontScale + 0.5f); | |||
| } | |||
| public static int sp2px(Context context, float spValue) { | |||
| final float fontScale =context.getResources().getDisplayMetrics().scaledDensity; | |||
| return (int) (spValue * fontScale + 0.5f); | |||
| } | |||
| public static int dp2px(Context context, float dipValue) { | |||
| final float scale = context.getResources().getDisplayMetrics().density; | |||
| return (int) (dipValue * scale + 0.5f); | |||
| } | |||
| public static int px2dp(Context context, float dipValue) { | |||
| final float scale = context.getResources().getDisplayMetrics().density; | |||
| return (int) (dipValue / scale + 0.5f); | |||
| } | |||
| } | |||
| @ -0,0 +1,105 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import com.handset.serialportsensor.constant.Constant; | |||
| public class ProtoUtils { | |||
| public static final int HEADER_BYTE_NUM = 2; | |||
| public static final int ID_BYTE_NUM = 4; | |||
| public static final int COMMAND_BYTE_NUM = 2; | |||
| private static final int MAX_MANUFACTURER_NO = 2; | |||
| private static final int MIN_MANUFACTURER_NO = 0; | |||
| public static final int MAX_MANUFACTURER_INTERNAL_NO = 999; | |||
| private static final int MIN_MANUFACTURER_INTERNAL_NO = 1; | |||
| public static int getCommandValue(int[] values) { | |||
| return (values[1] >> 8); | |||
| } | |||
| public static byte getIdHigh1(int[] values) { | |||
| return (byte) ((values[0] >> 24) & 0xFF); | |||
| } | |||
| public static byte getIdHigh2(int[] values) { | |||
| return (byte) ((values[0] >> 16) & 0xFF); | |||
| } | |||
| public static byte getIdHigh3(int[] values) { | |||
| return (byte) ((values[0] >> 8) & 0xFF); | |||
| } | |||
| public static byte getIdHigh4(int[] values) { | |||
| return (byte) (values[0] & 0xFF); | |||
| } | |||
| public static byte getIdHigh1(int low) { | |||
| return (byte) ((low >> 24) & 0xFF); | |||
| } | |||
| public static byte getIdHigh2(int low) { | |||
| return (byte) (low >> 16 & 0xFF); | |||
| } | |||
| public static byte getIdHigh3(int high) { | |||
| return (byte) ((high >> 8) & 0xFF); | |||
| } | |||
| public static byte getIdHigh4(int high) { | |||
| return (byte) (high & 0xFF); | |||
| } | |||
| public static byte[] getByte4Id(String id) { | |||
| byte year = (byte) Integer.parseInt(id.substring(0, 2)); | |||
| byte batch = (byte) Integer.parseInt(id.substring(2, 4)); | |||
| Integer num = Integer.parseInt(id.substring(4, 8)); | |||
| byte numHigh = (byte) (num >> 8 & 0xFF); | |||
| byte numLow = (byte) (num & 0xFF); | |||
| byte[] last = {year, batch, numHigh, numLow}; | |||
| return last; | |||
| } | |||
| public static byte[] genSentCommand11Byte(byte command, byte idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { | |||
| byte[] bytes1 = {idHigh1, idHigh2, idHigh3, idHigh4, 0x00, command, 0x00}; | |||
| int crc1021 = CRC16Utils.getCRC1021(bytes1); | |||
| byte low = (byte) (crc1021 & 0xff); | |||
| byte high = (byte) ((crc1021 >> 8) & 0xff); | |||
| byte[] getIdBuffer = {(byte) 0xDD, (byte) 0xDD, idHigh1, idHigh2, idHigh3, idHigh4, 0x00, command, 0x00, low, high}; | |||
| return getIdBuffer; | |||
| } | |||
| public static byte[] genSentCommandSetId(byte idHigh1, byte idHigh2, byte idHigh3, byte idHigh4, | |||
| byte nidHigh1, byte nidHigh2, byte nidHigh3, byte nidHigh4) { | |||
| byte[] bytes1 = {idHigh1, idHigh2, idHigh3, idHigh4, 0x00, Constant.Command.COMMAND_50, 0x04, nidHigh1, nidHigh2, nidHigh3, nidHigh4}; | |||
| int crc1021 = CRC16Utils.getCRC1021(bytes1); | |||
| byte low = (byte) (crc1021 & 0xff); | |||
| byte high = (byte) ((crc1021 >> 8) & 0xff); | |||
| byte[] getIdBuffer = {(byte) 0xDD, (byte) 0xDD, idHigh1, idHigh2, idHigh3, idHigh4, 0x00, Constant.Command.COMMAND_50, 0x04, | |||
| nidHigh1, nidHigh2, nidHigh3, nidHigh4, low, high}; | |||
| return getIdBuffer; | |||
| } | |||
| public static int[] getNumber(byte idHigh1, byte idHigh2) { | |||
| int id = (idHigh2 << 8) + idHigh1; | |||
| int interId = id % 1000;//厂家内部ID(0x0041-0x2fff) 0x6042 | |||
| int number = id / 1000;//厂家编号(0-4) | |||
| if (interId >= MIN_MANUFACTURER_INTERNAL_NO) { | |||
| if (number >= MIN_MANUFACTURER_NO && number <= MAX_MANUFACTURER_NO) { | |||
| return new int[]{number, interId}; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| public static int[] getSensorNumber(int idHigh1, byte idHigh2, byte idHigh3, byte idHigh4) { | |||
| int mId = Utils.byteArray2Int(new byte[]{idHigh3, idHigh4}); | |||
| int id = (idHigh1 * 100 + idHigh2) * 10000 + mId; | |||
| int number = mId / 1000;//厂家编号(0-4) | |||
| return new int[]{number, id}; | |||
| } | |||
| } | |||
| @ -0,0 +1,303 @@ | |||
| /* | |||
| ShengDao Android Client, PreferencesManager | |||
| Copyright (c) 2014 ShengDao Tech Company Limited | |||
| */ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| import android.content.SharedPreferences; | |||
| import android.content.SharedPreferences.Editor; | |||
| import android.text.TextUtils; | |||
| import java.io.File; | |||
| import java.lang.reflect.Field; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import java.util.Set; | |||
| /** | |||
| * [PreferencesManager管理类,提供get和put方法来重写SharedPreferences所提供的方法,更为实用和便捷] | |||
| * | |||
| * @author huxinwu | |||
| * @version 1.0 | |||
| * @date 2014-3-5 | |||
| **/ | |||
| @SuppressWarnings("ALL") | |||
| public class SPUtils { | |||
| private final String tag = SPUtils.class.getSimpleName(); | |||
| private Context mContext; | |||
| private SharedPreferences preferences; | |||
| private String DATA_URL = "/data/data/"; | |||
| private String SHARED_PREFS = "/shared_prefs"; | |||
| private static String shareName = "SHARE_DATA"; | |||
| public static final String THEME = "Theme"; | |||
| public static final String LANG = "Lang"; | |||
| private static SPUtils instance; | |||
| /** | |||
| * 构造方法 | |||
| * | |||
| * @param context | |||
| */ | |||
| private SPUtils(Context context) { | |||
| this(context, shareName); | |||
| } | |||
| /** | |||
| * 构造方法 | |||
| * | |||
| * @param context | |||
| * @param shareName | |||
| */ | |||
| private SPUtils(Context context, String shareName) { | |||
| mContext = context; | |||
| preferences = context.getSharedPreferences(shareName, | |||
| Context.MODE_PRIVATE); | |||
| } | |||
| /** | |||
| * 得到单例模式的PreferencesManager对象 | |||
| * | |||
| * @param context 上下文 | |||
| * @return | |||
| */ | |||
| public static SPUtils getInstance(Context context) { | |||
| return getInstance(context, shareName); | |||
| } | |||
| /** | |||
| * 得到单例模式的PreferencesManager对象 | |||
| * | |||
| * @param context 上下文 | |||
| * @param shareName 文件名称 | |||
| * @return | |||
| */ | |||
| public static SPUtils getInstance(Context context, | |||
| String shareName) { | |||
| if (instance == null) { | |||
| synchronized (SPUtils.class) { | |||
| if (instance == null) { | |||
| instance = new SPUtils(context, shareName); | |||
| } | |||
| } | |||
| } | |||
| return instance; | |||
| } | |||
| public void put(String key, boolean value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putBoolean(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| public void put(String key, String value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putString(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| public void put(String key, int value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putInt(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| public void put(String key, float value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putFloat(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| public void put(String key, long value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putLong(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| public void put(String key, Set<String> value) { | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putStringSet(key, value); | |||
| edit.commit(); | |||
| } | |||
| } | |||
| /** | |||
| * 直接存放对象,反射将根据对象的属性作为key,并将对应的值保存。 | |||
| * | |||
| * @param t | |||
| */ | |||
| @SuppressWarnings("rawtypes") | |||
| public <T> void put(T t) { | |||
| try { | |||
| String methodName = ""; | |||
| String saveValue = ""; | |||
| String fieldName = ""; | |||
| Editor edit = preferences.edit(); | |||
| Class cls = t.getClass(); | |||
| if (edit != null) { | |||
| Method[] methods = cls.getDeclaredMethods(); | |||
| Field[] fields = cls.getDeclaredFields(); | |||
| for (Method method : methods) { | |||
| methodName = method.getName(); | |||
| for (Field f : fields) { | |||
| fieldName = f.getName(); | |||
| if (methodName.toLowerCase().contains(fieldName.toLowerCase())) { | |||
| Object value = method.invoke(t); | |||
| if (value != null && !TextUtils.isEmpty(String.valueOf(value))) { | |||
| saveValue = String.valueOf(value); | |||
| } | |||
| edit.putString(fieldName, String.valueOf(saveValue)); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| edit.commit(); | |||
| } | |||
| } catch (IllegalAccessException e) { | |||
| e.printStackTrace(); | |||
| } catch (IllegalArgumentException e) { | |||
| e.printStackTrace(); | |||
| } catch (InvocationTargetException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| public String get(String key) { | |||
| return preferences.getString(key, ""); | |||
| } | |||
| public String get(String key, String defValue) { | |||
| return preferences.getString(key, defValue); | |||
| } | |||
| public boolean get(String key, boolean defValue) { | |||
| return preferences.getBoolean(key, defValue); | |||
| } | |||
| public int get(String key, int defValue) { | |||
| return preferences.getInt(key, defValue); | |||
| } | |||
| public float get(String key, float defValue) { | |||
| return preferences.getFloat(key, defValue); | |||
| } | |||
| public long get(String key, long defValue) { | |||
| return preferences.getLong(key, defValue); | |||
| } | |||
| public Set<String> get(String key, Set<String> defValue) { | |||
| return preferences.getStringSet(key, defValue); | |||
| } | |||
| /** | |||
| * 获取整个对象,跟put(T t)对应使用, 利用反射得到对象的属性,然后从preferences获取 | |||
| * | |||
| * @param cls | |||
| * @return | |||
| */ | |||
| public <T> T get(Class<T> cls) { | |||
| T obj = null; | |||
| String fieldName = ""; | |||
| try { | |||
| obj = cls.newInstance(); | |||
| Field[] fields = cls.getDeclaredFields(); | |||
| for (Field f : fields) { | |||
| fieldName = f.getName(); | |||
| if (!"serialVersionUID".equals(fieldName)) { | |||
| f.setAccessible(true); | |||
| f.set(obj, get(f.getName())); | |||
| } | |||
| } | |||
| } catch (InstantiationException e) { | |||
| e.printStackTrace(); | |||
| } catch (IllegalAccessException e) { | |||
| e.printStackTrace(); | |||
| } catch (IllegalArgumentException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return obj; | |||
| } | |||
| public int getTheme(int defThemeId) { | |||
| return instance.get(THEME, defThemeId); | |||
| } | |||
| public void setTheme(int themeId) { | |||
| instance.put(THEME, themeId); | |||
| } | |||
| public String getLanguage(String defLang) { | |||
| return instance.get(LANG, defLang); | |||
| } | |||
| public void setLang(String Language) { | |||
| instance.put(LANG, Language); | |||
| } | |||
| public void clearAll() { | |||
| try { | |||
| String fileName = shareName + ".xml"; | |||
| StringBuilder path = new StringBuilder(DATA_URL).append(mContext.getPackageName()).append(SHARED_PREFS); | |||
| File file = new File(path.toString(), fileName); | |||
| if (file.exists()) { | |||
| file.delete(); | |||
| } | |||
| } catch (Exception e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| /** | |||
| * 将对象以 json字符串的形式存到share preference里 | |||
| * | |||
| * @param key | |||
| * @param objeat | |||
| */ | |||
| /*public void put(String key, Object objeat) { | |||
| Gson gson = new Gson(); | |||
| String json = gson.toJson(objeat); | |||
| Editor edit = preferences.edit(); | |||
| if (edit != null) { | |||
| edit.putString(key, json); | |||
| edit.commit(); | |||
| } | |||
| }*/ | |||
| /** | |||
| * 将json字符串转成对象返回 | |||
| * | |||
| * @param key | |||
| * @param cls | |||
| * @param <T> | |||
| * @return | |||
| */ | |||
| /*public <T> T get(String key, Class<T> cls) { | |||
| //Slog.d("SmartHomePrefs", "setWatchesPhone "); | |||
| String json = preferences.getString(key, null); | |||
| Gson gson = new Gson(); | |||
| return gson.fromJson(json, cls); | |||
| }*/ | |||
| } | |||
| @ -0,0 +1,323 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.app.Activity; | |||
| import android.content.Context; | |||
| import android.os.Environment; | |||
| import android.os.storage.StorageManager; | |||
| import android.util.Log; | |||
| import java.io.BufferedWriter; | |||
| import java.io.File; | |||
| import java.io.FileWriter; | |||
| import java.io.IOException; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import java.text.SimpleDateFormat; | |||
| import java.util.ArrayList; | |||
| import java.util.Collections; | |||
| import java.util.Comparator; | |||
| import java.util.Date; | |||
| import java.util.List; | |||
| /** | |||
| * log 输出,保存。 | |||
| * Created by Jeremy on 2015-09-17. | |||
| */ | |||
| @SuppressWarnings("ALL") | |||
| public final class Slog { | |||
| public static boolean DEBUG = true; | |||
| public static boolean SHOW_ACTIVITY_STATE = true; | |||
| private static String LOG_FILE_FIRST_NAME = "com_htjc_sensor_"; | |||
| private final static String LOG_FILE_END_NAME = "_log.txt"; | |||
| private static int sLogLevel = 5; | |||
| public static final int VERBOSE_L = 5; | |||
| public static final int DEBUG_L = 4; | |||
| public static final int INFO_L = 3; | |||
| public static final int WARN_L = 2; | |||
| public static final int ERROR_L = 1; | |||
| private static int SDCARD_LOG_FILE_SAVE_NUM = 7;// sd卡中日志文件的最多保存个数 | |||
| private static final String ERROR_TYPE = "ERROR"; | |||
| private static final String WARN_TYPE = "WARNING"; | |||
| private static final String INFO_TYPE = "INFO"; | |||
| private static final String DEBUG_TYPE = "DEBUG"; | |||
| private static final String VERBOSE_TYPE = "VERBOSE"; | |||
| private static String sPath; | |||
| private static Context sContext; | |||
| private static boolean isSaveLog = false; | |||
| public static void init(Context context) { | |||
| sContext = context; | |||
| LOG_FILE_FIRST_NAME = context.getPackageName().replace(".", "_") + "_"; | |||
| } | |||
| /*use init(Context context) instead | |||
| * */ | |||
| @Deprecated | |||
| public static void init(Context context, String com, String pkgId) { | |||
| sContext = context; | |||
| LOG_FILE_FIRST_NAME = pkgId.replace(".", "_") + "_"; | |||
| } | |||
| public static void setDebug(boolean debug, boolean showActivityStatus) { | |||
| DEBUG = debug; | |||
| SHOW_ACTIVITY_STATE = showActivityStatus; | |||
| } | |||
| public static void enableSaveLog(boolean isSaveLog) { | |||
| Slog.isSaveLog = isSaveLog; | |||
| } | |||
| public static String getLogPath() { | |||
| return getSavePath(); | |||
| } | |||
| private Slog() { | |||
| } | |||
| public static void i(String tag, String msg) { | |||
| if (DEBUG) { | |||
| Log.i(tag, msg); | |||
| send("i", tag, msg); | |||
| } | |||
| } | |||
| public static void v(String tag, String msg) { | |||
| if (DEBUG) { | |||
| Log.v(tag, msg); | |||
| send("v", tag, msg); | |||
| } | |||
| } | |||
| public static void d(String tag, String msg) { | |||
| if (DEBUG) { | |||
| Log.d(tag, msg); | |||
| send("d", tag, msg); | |||
| } | |||
| } | |||
| public static void e(String tag, String msg) { | |||
| if (DEBUG) { | |||
| Log.e(tag, msg); | |||
| send("e", tag, msg); | |||
| } | |||
| } | |||
| public static void save(String tag, String msg) { | |||
| if (DEBUG) { | |||
| Log.d(tag, msg); | |||
| saveOP("d", tag, msg); | |||
| } | |||
| } | |||
| public static final void state(String packName, String state) { | |||
| if (SHOW_ACTIVITY_STATE) | |||
| Log.d(packName, state); | |||
| } | |||
| public static void send(String e, String tag, String msg) { | |||
| if (!isSaveLog) { | |||
| return; | |||
| } | |||
| String logmsg = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + | |||
| " " + e + " " + tag + " " + msg + ""; | |||
| writeLogToFile(getLogPath(), e, tag, logmsg); | |||
| delFile(getLogPath()); | |||
| } | |||
| /** | |||
| * 保存操作日志的log | |||
| */ | |||
| public static void saveOP(String e, String tag, String msg) { | |||
| if (!isSaveLog) { | |||
| return; | |||
| } | |||
| String logmsg = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " " + msg + ""; | |||
| writeLogToFileOP(getSavePathOP(), e, tag, logmsg); | |||
| delFile(getSavePathOP()); | |||
| } | |||
| /** | |||
| * 打开日志文件并写入日志 | |||
| * | |||
| * @return | |||
| **/ | |||
| private static void writeLogToFileOP(String path, String type, String tag, String text) {// 新建或打开日志文件 | |||
| try { | |||
| String needWriteFile = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); | |||
| File file = getFileOP(path, needWriteFile); | |||
| FileWriter filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖 | |||
| BufferedWriter bufWriter = new BufferedWriter(filerWriter); | |||
| String needWriteMessage = new String(text.getBytes(), "utf-8") + "\"\n" + "\n"; | |||
| bufWriter.write(needWriteMessage); | |||
| bufWriter.newLine(); | |||
| bufWriter.close(); | |||
| filerWriter.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| /** | |||
| * 打开日志文件并写入日志 | |||
| * | |||
| * @return | |||
| **/ | |||
| private static void writeLogToFile(String path, String type, String tag, String text) {// 新建或打开日志文件 | |||
| try { | |||
| String needWriteFile = new SimpleDateFormat("yyyy_MM_dd").format(new Date()); | |||
| File file = getFile(path, needWriteFile); | |||
| FileWriter filerWriter = new FileWriter(file, true);//后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖 | |||
| BufferedWriter bufWriter = new BufferedWriter(filerWriter); | |||
| String needWriteMessage = new String(text.getBytes(), "utf-8") + "\"\n" + "\n"; | |||
| bufWriter.write(needWriteMessage); | |||
| bufWriter.newLine(); | |||
| bufWriter.close(); | |||
| filerWriter.close(); | |||
| } catch (IOException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| /** | |||
| * 删除多余的日志文件,只保留SDCARD_LOG_FILE_SAVE_NUM个 | |||
| */ | |||
| public static void delFile(String path) {// 删除日志文件 | |||
| List<File> files = getFileSort(path); | |||
| if (files != null) { | |||
| for (int i = 0; i < files.size(); i++) { | |||
| if (i >= SDCARD_LOG_FILE_SAVE_NUM && files.get(i).exists()) { | |||
| files.get(i).delete(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| public static File getFile(String savepath, String time) { | |||
| File savePath = new File(savepath); | |||
| if (!savePath.exists()) { | |||
| savePath.mkdirs(); | |||
| } | |||
| File file = new File(savePath, LOG_FILE_FIRST_NAME + time | |||
| + LOG_FILE_END_NAME); | |||
| return file; | |||
| } | |||
| public static File getFileOP(String savepath, String time) { | |||
| File savePath = new File(savepath); | |||
| if (!savePath.exists()) { | |||
| savePath.mkdirs(); | |||
| } | |||
| File file = new File(savePath, time | |||
| + LOG_FILE_END_NAME); | |||
| return file; | |||
| } | |||
| /** | |||
| * 获取目录下所有文件 | |||
| * | |||
| * @param realpath | |||
| * @param files | |||
| * @return | |||
| */ | |||
| public static List<File> getFiles(String realpath, List<File> files) { | |||
| File realFile = new File(realpath); | |||
| if (realFile.isDirectory()) { | |||
| File[] subfiles = realFile.listFiles(); | |||
| if (subfiles != null) { | |||
| for (File file : subfiles) { | |||
| if (file.isDirectory()) { | |||
| getFiles(file.getAbsolutePath(), files); | |||
| } else { | |||
| files.add(file); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return files; | |||
| } | |||
| public static List<File> getOperateLogFiles() { | |||
| return getFileSort(getSavePathOP()); | |||
| } | |||
| /** | |||
| * 获取目录下所有文件(按时间倒序排序) | |||
| * | |||
| * @return | |||
| */ | |||
| public static List<File> getFileSort(String savePath) { | |||
| File save = new File(savePath); | |||
| if (!save.exists()) { | |||
| return null; | |||
| } | |||
| List<File> list = getFiles(savePath, new ArrayList<File>()); | |||
| if (list != null && list.size() > 0) { | |||
| Collections.sort(list, new Comparator<File>() { | |||
| @Override | |||
| public int compare(File file, File newFile) { | |||
| if (file.lastModified() > newFile.lastModified()) { | |||
| return -1; | |||
| } else if (file.lastModified() == newFile.lastModified()) { | |||
| return 0; | |||
| } else { | |||
| return 1; | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| return list; | |||
| } | |||
| public static String getSavePath() { | |||
| return Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "applog/"; | |||
| } | |||
| public static String getSavePathOP() { | |||
| return Environment.getExternalStorageDirectory().getAbsolutePath() | |||
| + File.separator + "htjc" + File.separator + "sensor" + File.separator + "operatelog/"; | |||
| } | |||
| public static class StorageList { | |||
| private Context mContext; | |||
| private StorageManager mStorageManager; | |||
| private Method mMethodGetPaths; | |||
| public StorageList(Context context) { | |||
| mContext = context; | |||
| if (mContext != null) { | |||
| mStorageManager = (StorageManager) mContext | |||
| .getSystemService(Activity.STORAGE_SERVICE); | |||
| try { | |||
| mMethodGetPaths = mStorageManager.getClass() | |||
| .getMethod("getVolumePaths"); | |||
| } catch (NoSuchMethodException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| } | |||
| } | |||
| public String[] getVolumePaths() { | |||
| String[] paths = null; | |||
| try { | |||
| paths = (String[]) mMethodGetPaths.invoke(mStorageManager); | |||
| } catch (IllegalArgumentException e) { | |||
| e.printStackTrace(); | |||
| } catch (IllegalAccessException e) { | |||
| e.printStackTrace(); | |||
| } catch (InvocationTargetException e) { | |||
| e.printStackTrace(); | |||
| } | |||
| return paths; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,159 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| import android.content.SharedPreferences; | |||
| import java.lang.reflect.InvocationTargetException; | |||
| import java.lang.reflect.Method; | |||
| import java.util.Map; | |||
| /** | |||
| * Created by yxm on 16-6-23. | |||
| */ | |||
| public class SpUtil { | |||
| /** | |||
| * 保存在手机里面的文件名 | |||
| */ | |||
| public static final String FILE_NAME = "share_data"; | |||
| /** | |||
| * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法 | |||
| */ | |||
| public static void put(Context context, String key, Object object) { | |||
| put(context, FILE_NAME, key, object); | |||
| } | |||
| public static void put(Context context, String spName, String key, Object object) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, | |||
| Context.MODE_PRIVATE); | |||
| SharedPreferences.Editor editor = sp.edit(); | |||
| if (object instanceof String) { | |||
| editor.putString(key, (String) object); | |||
| } else if (object instanceof Integer) { | |||
| editor.putInt(key, (Integer) object); | |||
| } else if (object instanceof Boolean) { | |||
| editor.putBoolean(key, (Boolean) object); | |||
| } else if (object instanceof Float) { | |||
| editor.putFloat(key, (Float) object); | |||
| } else if (object instanceof Long) { | |||
| editor.putLong(key, (Long) object); | |||
| } else { | |||
| editor.putString(key, object.toString()); | |||
| } | |||
| SharedPreferencesCompat.apply(editor); | |||
| } | |||
| /** | |||
| * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值 | |||
| */ | |||
| public static Object get(Context context, String key, Object defaultObject) { | |||
| return get(context, FILE_NAME, key, defaultObject); | |||
| } | |||
| public static Object get(Context context, String spName, String key, Object defaultObject) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, | |||
| Context.MODE_PRIVATE); | |||
| if (defaultObject instanceof String) { | |||
| return sp.getString(key, (String) defaultObject); | |||
| } else if (defaultObject instanceof Integer) { | |||
| return sp.getInt(key, (Integer) defaultObject); | |||
| } else if (defaultObject instanceof Boolean) { | |||
| return sp.getBoolean(key, (Boolean) defaultObject); | |||
| } else if (defaultObject instanceof Float) { | |||
| return sp.getFloat(key, (Float) defaultObject); | |||
| } else if (defaultObject instanceof Long) { | |||
| return sp.getLong(key, (Long) defaultObject); | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * 移除某个key值已经对应的值 | |||
| */ | |||
| public static void remove(Context context, String key) { | |||
| remove(context, FILE_NAME, key); | |||
| } | |||
| public static void remove(Context context, String spName, String key) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, | |||
| Context.MODE_PRIVATE); | |||
| SharedPreferences.Editor editor = sp.edit(); | |||
| editor.remove(key); | |||
| SharedPreferencesCompat.apply(editor); | |||
| } | |||
| /** | |||
| * 清除所有数据 | |||
| */ | |||
| public static void clear(Context context) { | |||
| clear(context, FILE_NAME); | |||
| } | |||
| public static void clear(Context context, String spName) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE); | |||
| SharedPreferences.Editor editor = sp.edit(); | |||
| editor.clear(); | |||
| SharedPreferencesCompat.apply(editor); | |||
| } | |||
| /** | |||
| * 查询某个key是否已经存在 | |||
| */ | |||
| public static boolean contains(Context context, String key) { | |||
| return contains(context, FILE_NAME, key); | |||
| } | |||
| public static boolean contains(Context context, String spName, String key) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE); | |||
| return sp.contains(key); | |||
| } | |||
| /** | |||
| * 返回所有的键值对 | |||
| */ | |||
| public static Map getAll(Context context) { | |||
| return getAll(context, FILE_NAME); | |||
| } | |||
| public static Map getAll(Context context, String spName) { | |||
| SharedPreferences sp = context.getSharedPreferences(spName, | |||
| Context.MODE_PRIVATE); | |||
| return sp.getAll(); | |||
| } | |||
| /** | |||
| * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类 | |||
| */ | |||
| private static class SharedPreferencesCompat { | |||
| private static final Method sApplyMethod = findApplyMethod(); | |||
| /** | |||
| * 反射查找apply的方法 | |||
| */ | |||
| @SuppressWarnings({"unchecked", "rawtypes"}) | |||
| private static Method findApplyMethod() { | |||
| try { | |||
| Class clz = SharedPreferences.Editor.class; | |||
| return clz.getMethod("apply"); | |||
| } catch (NoSuchMethodException e) { | |||
| } | |||
| return null; | |||
| } | |||
| /** | |||
| * 如果找到则使用apply执行,否则使用commit | |||
| */ | |||
| public static void apply(SharedPreferences.Editor editor) { | |||
| try { | |||
| if (sApplyMethod != null) { | |||
| sApplyMethod.invoke(editor); | |||
| return; | |||
| } | |||
| } catch (IllegalArgumentException e) { | |||
| } catch (IllegalAccessException e) { | |||
| } catch (InvocationTargetException e) { | |||
| } | |||
| editor.commit(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,30 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.util.Log; | |||
| import com.google.common.base.Splitter; | |||
| import com.handset.serialportlib.ByteUtils; | |||
| import java.util.Collections; | |||
| public class SplitUtils { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| public static Iterable<String> split(String raw) { | |||
| try { | |||
| if (raw.length() == 22) { | |||
| return Splitter.fixedLength(22).split(raw); | |||
| } else if (raw.length() == 28) { | |||
| return Splitter.fixedLength(28).split(raw); | |||
| } else if(raw.length() > 28){ | |||
| byte[] bytes = ByteUtils.hexStrToBytes(raw); | |||
| int len = bytes[8] & 0xff; | |||
| int resLen = 18 + len * 2 + 4; | |||
| Log.i(logTag, "split len: " + len + ", resLen: " + resLen); | |||
| return Splitter.fixedLength(resLen).split(raw); | |||
| } else return Collections.emptyList(); | |||
| } catch (Exception e) { | |||
| return Collections.emptyList(); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,36 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.app.Activity; | |||
| import android.graphics.Color; | |||
| import android.os.Build; | |||
| import android.support.annotation.ColorRes; | |||
| import android.support.v4.content.ContextCompat; | |||
| import android.view.View; | |||
| import android.view.Window; | |||
| import android.view.WindowManager; | |||
| public class StatusBarUtils { | |||
| public static void setStatusColor(Activity activity, boolean isTranslate, boolean isDarkText, @ColorRes int bgColor) { | |||
| //如果系统为6.0及以上,就可以使用Android自带的方式 | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | |||
| Window window = activity.getWindow(); | |||
| View decorView = window.getDecorView(); | |||
| window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); //可有可无 | |||
| decorView.setSystemUiVisibility((isTranslate ? View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN : 0) | (isDarkText ? View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0)); | |||
| window.setStatusBarColor(isTranslate ? Color.TRANSPARENT : ContextCompat.getColor(activity, bgColor)); //Android5.0就可以用 | |||
| } | |||
| } | |||
| public static void setTranslucentStatus(Activity activity) { | |||
| // 5.0以上系统状态栏透明 | |||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |||
| Window window = activity.getWindow(); | |||
| window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | |||
| window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); | |||
| window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); | |||
| window.setStatusBarColor(Color.TRANSPARENT); | |||
| } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { | |||
| activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,169 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.app.AlertDialog; | |||
| import android.text.TextUtils; | |||
| import android.view.View; | |||
| import android.view.animation.Animation; | |||
| import android.view.animation.AnimationUtils; | |||
| import android.view.animation.LinearInterpolator; | |||
| import android.widget.Button; | |||
| import android.widget.ImageView; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.activity.BaseActivity; | |||
| public class ToastHelper { | |||
| public interface OnDialogClickListener { | |||
| void onOKClickListener(View view); | |||
| void onCancelClickListener(View view); | |||
| } | |||
| public interface OnDialogSubmitClickListener { | |||
| void onOKClickListener(View view); | |||
| } | |||
| public static AlertDialog showSubmitDialog(final String title, int icon, String content, int btnBgColor, String ok, BaseActivity context, final OnDialogSubmitClickListener listener) { | |||
| AlertDialog dialog = showSubmitDialogNoShow(title, icon, content, btnBgColor, ok, context, listener); | |||
| context.showDialog(dialog); | |||
| return dialog; | |||
| } | |||
| private static AlertDialog showSubmitDialogNoShow(final String title, int icon, String content, int btnBgColor, String ok, BaseActivity context, final OnDialogSubmitClickListener listener) { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_btl_recognition_error, (null)); | |||
| final AlertDialog dialog = builder.create(); | |||
| dialog.setView(view); | |||
| TextView tvTitle = view.findViewById(R.id.tv_title); | |||
| tvTitle.setText(title); | |||
| ImageView ivImg = view.findViewById(R.id.iv_img); | |||
| ivImg.setImageResource(icon); | |||
| TextView tvContent = view.findViewById(R.id.tv_content); | |||
| tvContent.setText(content); | |||
| Button btnConfirm = view.findViewById(R.id.btn_confirm); | |||
| btnConfirm.setBackgroundColor(btnBgColor); | |||
| if (!TextUtils.isEmpty(ok)) { | |||
| btnConfirm.setText(ok); | |||
| } | |||
| btnConfirm.setOnClickListener((View view2) -> { | |||
| dialog.dismiss(); | |||
| listener.onOKClickListener(view2); | |||
| }); | |||
| return dialog; | |||
| } | |||
| public static AlertDialog showChooseDialogNoShow(final String title, int icon, String content, int btnBgColor, String confirm, String cancel, BaseActivity context, final OnDialogClickListener listener) { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_stop_test, (null)); | |||
| final AlertDialog dialog = builder.create(); | |||
| dialog.setView(view); | |||
| TextView tvTitle = view.findViewById(R.id.tv_title); | |||
| tvTitle.setText(title); | |||
| ImageView ivImg = view.findViewById(R.id.iv_img); | |||
| ivImg.setImageResource(icon); | |||
| TextView tvContent = view.findViewById(R.id.tv_content); | |||
| tvContent.setText(content); | |||
| Button btnConfirm = view.findViewById(R.id.btn_confirm); | |||
| btnConfirm.setBackgroundColor(btnBgColor); | |||
| if (!TextUtils.isEmpty(confirm)) { | |||
| btnConfirm.setText(confirm); | |||
| } | |||
| btnConfirm.setOnClickListener((View view2) -> { | |||
| dialog.dismiss(); | |||
| listener.onOKClickListener(view2); | |||
| }); | |||
| Button btnCancel = view.findViewById(R.id.btn_cancel); | |||
| if (!TextUtils.isEmpty(cancel)) { | |||
| btnCancel.setText(cancel); | |||
| } | |||
| btnCancel.setOnClickListener((View view3) -> { | |||
| dialog.dismiss(); | |||
| listener.onCancelClickListener(view3); | |||
| }); | |||
| return dialog; | |||
| } | |||
| public static AlertDialog showTipDialog(BaseActivity context, int imgRes, int tips) { | |||
| return showTipDialog(context, imgRes, tips, (false)); | |||
| } | |||
| public static AlertDialog showTipDialogAnimation(BaseActivity context, int imgRes, int tips) { | |||
| return showTipDialog(context, imgRes, tips, (true)); | |||
| } | |||
| public static AlertDialog showTipDialogNoShow(BaseActivity context, int imgRes, int tips) { | |||
| return showTipDialogNoShow(context, imgRes, tips, (false)); | |||
| } | |||
| private static AlertDialog showTipDialog(BaseActivity context, int imgRes, int tips, boolean showAnimation) { | |||
| AlertDialog dialog = showTipDialogNoShow(context, imgRes, tips, showAnimation); | |||
| context.showDialog(dialog); | |||
| return dialog; | |||
| } | |||
| private static AlertDialog showTipDialogNoShow(BaseActivity context, int imgRes, int tips, boolean showAnimation) { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_tips_layout, (null)); | |||
| final AlertDialog dialog = builder.create(); | |||
| if (dialog.getWindow() != null) { | |||
| dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); | |||
| } | |||
| dialog.setView(view); | |||
| dialog.setCanceledOnTouchOutside(false); | |||
| dialog.setCancelable(false); | |||
| ImageView ivImg = view.findViewById(R.id.iv_loading); | |||
| if (imgRes != 0) { | |||
| ivImg.setVisibility(View.VISIBLE); | |||
| ivImg.setImageResource(imgRes); | |||
| } else { | |||
| ivImg.setVisibility(View.GONE); | |||
| } | |||
| if (showAnimation) { | |||
| Animation animation = AnimationUtils.loadAnimation(context, R.anim.rotate_anim); | |||
| animation.setInterpolator(new LinearInterpolator()); | |||
| ivImg.startAnimation(animation); | |||
| } | |||
| TextView tvTip = view.findViewById(R.id.tv_loading); | |||
| tvTip.setText(tips); | |||
| return dialog; | |||
| } | |||
| public static void showResetSensorDialog(BaseActivity context, final OnDialogClickListener listener) { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_chuchang, (null)); | |||
| final AlertDialog dialog = builder.create(); | |||
| dialog.setView(view); | |||
| Button btnCancel = view.findViewById(R.id.btn_cancel); | |||
| Button btnConfirm = view.findViewById(R.id.btn_confirm); | |||
| btnCancel.setOnClickListener((View view2) -> { | |||
| dialog.dismiss(); | |||
| listener.onCancelClickListener(view2); | |||
| }); | |||
| btnConfirm.setOnClickListener((View view3) -> { | |||
| dialog.dismiss(); | |||
| listener.onOKClickListener(view3); | |||
| }); | |||
| context.showDialog(dialog); | |||
| } | |||
| public static void showSaveSensorDialog(BaseActivity context, final OnDialogClickListener listener) { | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_save_alert, (null)); | |||
| final AlertDialog dialog = builder.create(); | |||
| dialog.setCancelable(false); | |||
| dialog.setView(view); | |||
| Button btnCancel = view.findViewById(R.id.btn_cancel); | |||
| Button btnConfirm = view.findViewById(R.id.btn_confirm); | |||
| btnCancel.setOnClickListener((View view2) -> { | |||
| dialog.dismiss(); | |||
| listener.onCancelClickListener(view2); | |||
| }); | |||
| btnConfirm.setOnClickListener((View view3) -> { | |||
| dialog.dismiss(); | |||
| listener.onOKClickListener(view3); | |||
| }); | |||
| context.showDialog(dialog); | |||
| } | |||
| } | |||
| @ -0,0 +1,203 @@ | |||
| package com.handset.serialportsensor.utils; | |||
| import android.content.Context; | |||
| import android.util.Log; | |||
| import java.io.File; | |||
| import java.io.FileOutputStream; | |||
| import java.math.BigInteger; | |||
| public class Utils { | |||
| private static final String path = "/sys/class/peijian_dev/function/PeijianPowerEn"; | |||
| private static final String path1 = "/sys/class/peijian_dev/function/pogo_wake"; | |||
| private final static String TAG = "Util"; | |||
| public static void initBLNStatus(char status) { | |||
| setBLNStatus(status, path); | |||
| setBLNStatus(status, path1); | |||
| } | |||
| private static void setBLNStatus(char status, String path) { | |||
| File file = new File(path); | |||
| FileOutputStream fos; | |||
| try { | |||
| if (!file.exists()) { | |||
| return; | |||
| } | |||
| fos = new FileOutputStream(file); | |||
| fos.write(status); | |||
| fos.close(); | |||
| } catch (Exception e) { | |||
| Log.e("setBLNStatus", "setBLNStatus error: ", e); | |||
| } | |||
| } | |||
| //低位在前,高位在后 | |||
| public static byte[] intToByte(int num) { | |||
| byte[] bytes = new byte[4]; | |||
| bytes[0] = (byte) ((num >> 24) & 0xff); | |||
| bytes[1] = (byte) ((num >> 16) & 0xff); | |||
| bytes[2] = (byte) ((num >> 8) & 0xff); | |||
| bytes[3] = (byte) (num & 0xff); | |||
| return bytes; | |||
| } | |||
| public static byte[] addBytes(byte[] data1, byte[] data2) { | |||
| byte[] data = new byte[data1.length + data2.length]; | |||
| System.arraycopy(data1, 0, data, 0, data1.length); | |||
| System.arraycopy(data2, 0, data, data1.length, data2.length); | |||
| return data; | |||
| } | |||
| public static byte[] addCheckBytes(byte[] byteCommand, int data) { | |||
| byte[] bytes2 = Utils.intToByte(data);//data | |||
| byte[] bytes3 = Utils.addBytes(byteCommand, bytes2); | |||
| int crc1021Egg = CRC16Utils.getCRC1021(bytes3); | |||
| byte[] bytes4 = Utils.intToByte(crc1021Egg); | |||
| return Utils.addBytes(bytes3, bytes4); | |||
| } | |||
| //根据ID获取厂家编号和厂家内部ID | |||
| public static int[] getNumber(int id) { | |||
| //id 厂家ID (number)*0x3000+(interId) | |||
| int b = 0x3000; | |||
| int low = 0x0041; | |||
| int high = 0x2fff; | |||
| int interId = id % b;//厂家内部ID(0x0041-0x2fff) 0x6042 | |||
| int number = id / b;//厂家编号(0-4) | |||
| if (interId >= low && interId <= high) { | |||
| if (number >= 0 && number <= 4) { | |||
| return new int[]{number, interId}; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| //低位在前,高位在后 | |||
| public static byte[] convertStringToHex(String str) { | |||
| char[] ch = str.toCharArray(); | |||
| byte[] hex = new byte[ch.length]; | |||
| for (int i = 0; i < ch.length; i++) { | |||
| hex[i] = (byte) ch[i]; | |||
| } | |||
| return hex; | |||
| } | |||
| public static byte[] convertStringToHexDesc(String str) { | |||
| char[] ch = str.toCharArray(); | |||
| byte[] hex = new byte[ch.length]; | |||
| for (int i = 0; i < ch.length; i++) { | |||
| hex[i] = (byte) ch[ch.length - i - 1]; | |||
| } | |||
| return hex; | |||
| } | |||
| public static String convertHexToString(String hex) { | |||
| StringBuilder sb = new StringBuilder(); | |||
| StringBuilder temp = new StringBuilder(); | |||
| for (int i = 0; i < hex.length() - 1; i += 2) { | |||
| //grab the hex in pairs | |||
| String output = hex.substring(i, (i + 2)); | |||
| //convert hex to decimal | |||
| int decimal = Integer.parseInt(output, 16); | |||
| //convert the decimal to character | |||
| sb.append((char) decimal); | |||
| temp.append(decimal); | |||
| } | |||
| return sb.toString(); | |||
| } | |||
| public static int dp2px(Context context, float dpValue) { | |||
| float scale = context.getResources().getDisplayMetrics().density; | |||
| return (int) (dpValue * scale + 0.5f); | |||
| } | |||
| public static int sp2px(Context context, float spValue) { | |||
| final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; | |||
| return (int) (spValue * fontScale + 0.5f); | |||
| } | |||
| public static byte[] getCrcByte(byte[] command, String data) { | |||
| byte[] hex = Utils.convertStringToHex(data); | |||
| byte[] bytes2 = Utils.addBytes(command, hex); | |||
| int crc1021 = CRC16Utils.getCRC1021(bytes2); | |||
| byte low = (byte) (crc1021 & 0xff); | |||
| byte high = (byte) ((crc1021 >> 8) & 0xff); | |||
| byte[] getBaudBuffer = new byte[bytes2.length + 4]; | |||
| getBaudBuffer[0] = (byte) 0xDD; | |||
| getBaudBuffer[1] = (byte) 0xDD; | |||
| for (int i = 0; i < bytes2.length; i++) { | |||
| getBaudBuffer[i + 2] = bytes2[i]; | |||
| } | |||
| getBaudBuffer[getBaudBuffer.length - 2] = low; | |||
| getBaudBuffer[getBaudBuffer.length - 1] = high; | |||
| return getBaudBuffer; | |||
| } | |||
| public static byte[] getCrcByte(byte[] command) { | |||
| int crc1021 = CRC16Utils.getCRC1021(command); | |||
| byte low = (byte) (crc1021 & 0xff); | |||
| byte high = (byte) ((crc1021 >> 8) & 0xff); | |||
| byte[] getBaudBuffer = new byte[command.length + 4]; | |||
| getBaudBuffer[0] = (byte) 0xDD; | |||
| getBaudBuffer[1] = (byte) 0xDD; | |||
| for (int i = 0; i < command.length; i++) { | |||
| getBaudBuffer[i + 2] = command[i]; | |||
| } | |||
| getBaudBuffer[getBaudBuffer.length - 2] = low; | |||
| getBaudBuffer[getBaudBuffer.length - 1] = high; | |||
| return getBaudBuffer; | |||
| } | |||
| public static String byteArrayToString(byte[] b) { | |||
| StringBuilder hexBuilder = new StringBuilder(); | |||
| for (byte aB : b) { | |||
| String hexString = Integer.toHexString(aB & 0xFF); | |||
| if (hexString.length() < 2) { | |||
| hexBuilder.append(0); | |||
| } | |||
| hexBuilder.append(hexString); | |||
| } | |||
| BigInteger bigInteger = new BigInteger(hexBuilder.toString(), 16); | |||
| String s = bigInteger.toString(10); | |||
| return s; | |||
| } | |||
| public final static int getInt(byte[] buf, boolean asc, int len) { | |||
| if (buf == null) { | |||
| throw new IllegalArgumentException("byte array is null!"); | |||
| } | |||
| if (len > 4) { | |||
| throw new IllegalArgumentException("byte array size > 4 !"); | |||
| } | |||
| int r = 0; | |||
| if (asc) | |||
| for (int i = len - 1; i >= 0; i--) { | |||
| r <<= 8; | |||
| r |= (buf[i] & 0x000000ff); | |||
| } | |||
| else | |||
| for (int i = 0; i < len; i++) { | |||
| r <<= 8; | |||
| r |= (buf[i] & 0x000000ff); | |||
| } | |||
| return r; | |||
| } | |||
| public final static int byteArray2Int(byte[] buf) { | |||
| return getInt(buf, false, 2); | |||
| } | |||
| public static String getSensorNoShow(String raw) { | |||
| if(raw.length() < 8) { | |||
| return raw; | |||
| } | |||
| StringBuilder sb = new StringBuilder(raw); | |||
| sb.deleteCharAt(4); | |||
| return sb.toString(); | |||
| } | |||
| } | |||
| @ -0,0 +1,169 @@ | |||
| package com.handset.serialportsensor.view; | |||
| import android.content.Context; | |||
| import android.text.TextUtils; | |||
| import android.util.AttributeSet; | |||
| import android.view.LayoutInflater; | |||
| import android.view.View; | |||
| import android.widget.AbsListView; | |||
| import android.widget.LinearLayout; | |||
| import android.widget.ListAdapter; | |||
| import android.widget.ListView; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| /** | |||
| * 目前很多App的ListView都有在分页显示时自动加载更多内容的功能,既: | |||
| * 1 每次只显示一页内容; | |||
| * 2 用户滚动到底部的时候,则会出现一行“正在加载”的提示并开始加载; | |||
| * 3 如果全部内容都加载完成了,则滚动到底部不会出现提示。 | |||
| * <p> | |||
| * AutoLoadMoreListView在标准ListView的基础上,进行了简单的封装来实现这个功能; | |||
| * 1 “正在加载”的提示是一个footer,默认实现是文字加旋转动画; | |||
| * 2 可以指定footer的高度,背景颜色,文字等属性,也可以替换为自定义的layout; | |||
| * 3 footer是否显示由调用者决定; | |||
| * 4 当滚动到底部的时候,通过回调通知应用执行加载,加载完成后要告知加载完成; | |||
| */ | |||
| public class AutoLoadMoreListView extends ListView implements AbsListView.OnScrollListener { | |||
| private View mLoadStatus; | |||
| private View mLoadMoreView; | |||
| //控制moreView的显示,是否显示是由调用者来决定的 | |||
| private boolean mShowLoadMore; | |||
| private AutoLoadMoreListener mLoadMoreListener; | |||
| //是否正在执行加载更多的动作,防止重复调用 | |||
| private boolean mDoingLoadMore; | |||
| public AutoLoadMoreListView(Context context) { | |||
| super(context); | |||
| init(null, 0); | |||
| } | |||
| public AutoLoadMoreListView(Context context, AttributeSet attrs) { | |||
| super(context, attrs); | |||
| init(attrs, 0); | |||
| } | |||
| public AutoLoadMoreListView(Context context, AttributeSet attrs, int defStyle) { | |||
| super(context, attrs, defStyle); | |||
| init(attrs, defStyle); | |||
| } | |||
| private void init(AttributeSet attrs, int defStyle) { | |||
| mLoadMoreView = LayoutInflater.from(getContext()).inflate(R.layout.simple_auto_load_more, null); | |||
| mLoadStatus = LayoutInflater.from(getContext()).inflate(R.layout.simple_auto_load_more, null); | |||
| setOnScrollListener(this); | |||
| } | |||
| @Override | |||
| public void onScrollStateChanged(AbsListView view, int scrollState) { | |||
| } | |||
| @Override | |||
| public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { | |||
| //检查是否要通知App去做加载更多 | |||
| if (mShowLoadMore && (!mDoingLoadMore) | |||
| && mLoadMoreListener != null | |||
| && (firstVisibleItem + visibleItemCount) >= totalItemCount) { | |||
| mDoingLoadMore = true; | |||
| mLoadMoreListener.onLoadMoreBegin(this); | |||
| } | |||
| } | |||
| /** | |||
| * 设置是否显示“加载更多”footer | |||
| * | |||
| * @param show | |||
| */ | |||
| public void setShowLoadMore(boolean show) { | |||
| if (show == mShowLoadMore) { | |||
| return; | |||
| } | |||
| updateFoot(""); | |||
| mShowLoadMore = show; | |||
| if (mShowLoadMore) { | |||
| this.addFooterView(mLoadMoreView); | |||
| } else { | |||
| this.removeFooterView(mLoadMoreView); | |||
| } | |||
| } | |||
| public void setLoadMoreListener(AutoLoadMoreListener listener) { | |||
| mLoadMoreListener = listener; | |||
| } | |||
| /** | |||
| * App设置是否加载更多动作已经完成 | |||
| * 只有本次加载完成了,当滚动到底部的时候,才能再次发起加载 | |||
| */ | |||
| public void loadMoreComplete() { | |||
| mDoingLoadMore = false; | |||
| updateFoot("数据已经全部加载"); | |||
| } | |||
| /** | |||
| * 设置默认的加载更多footer的属性 | |||
| * | |||
| * @param height 高度 px | |||
| * @param bgColor 背景颜色 | |||
| * @param textSize 文字大小 sp | |||
| * @param textColor 文字颜色 | |||
| */ | |||
| public void setupDefaultLoadMoreView(int height, int bgColor, int textSize, int textColor) { | |||
| mLoadMoreView.setBackgroundColor(bgColor); | |||
| View v = mLoadMoreView.findViewById(R.id.auto_load_more_container); | |||
| LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) v | |||
| .getLayoutParams(); | |||
| lp.height = height; | |||
| v.setLayoutParams(lp); | |||
| TextView textView = mLoadMoreView.findViewById(R.id.auto_load_more_text); | |||
| textView.setTextSize(textSize); | |||
| textView.setTextColor(textColor); | |||
| } | |||
| boolean showFootStatus = false; | |||
| public void updateFoot(String s) { | |||
| if (TextUtils.isEmpty(s)) { | |||
| if (showFootStatus) { | |||
| this.removeFooterView(mLoadStatus); | |||
| } | |||
| showFootStatus = false; | |||
| } else { | |||
| if (!showFootStatus) { | |||
| this.addFooterView(mLoadStatus); | |||
| } | |||
| TextView textView = mLoadStatus.findViewById(R.id.auto_load_more_text); | |||
| textView.setText(s); | |||
| showFootStatus = true; | |||
| } | |||
| } | |||
| /** | |||
| * 设置自定义的加载更多footer | |||
| * | |||
| * @param view | |||
| */ | |||
| public void setCustomLoadMoreView(View view) { | |||
| mLoadMoreView = view; | |||
| } | |||
| /** | |||
| * 在android4.2.2的机器上遇到一个问题,调用addFooterView的时候报 | |||
| * ListDataBindingAdapter cannot be cast to android.widget.HeaderViewListAdapter | |||
| * 在网上查找后得知,在Api18以下的机器,Wrapping做得不太好,可以用如下方法来规避。 | |||
| * | |||
| * @param adapter 适配器 | |||
| */ | |||
| @Override | |||
| public void setAdapter(ListAdapter adapter) { | |||
| this.addFooterView(mLoadMoreView); | |||
| super.setAdapter(adapter); | |||
| this.removeFooterView(mLoadMoreView); | |||
| } | |||
| } | |||
| @ -0,0 +1,9 @@ | |||
| package com.handset.serialportsensor.view; | |||
| /** | |||
| * Created by LiGang on 2016/4/30. | |||
| */ | |||
| public interface AutoLoadMoreListener { | |||
| //通知App Listview已经滚动到底部,开始加载下一页数据 | |||
| void onLoadMoreBegin(final AutoLoadMoreListView listView); | |||
| } | |||
| @ -0,0 +1,61 @@ | |||
| package com.handset.serialportsensor.view; | |||
| import android.app.Activity; | |||
| import android.app.AlertDialog; | |||
| import android.view.View; | |||
| import android.widget.Button; | |||
| import android.widget.TextView; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.activity.BaseActivity; | |||
| import com.handset.serialportsensor.utils.ToastHelper; | |||
| /** | |||
| * Created by zy on 2019/3/7. | |||
| */ | |||
| public class ExportProgressDialog { | |||
| private TextView tvContent; | |||
| private Button mButton; | |||
| public AlertDialog mAlertDialog; | |||
| private String ss; | |||
| public AlertDialog showExportDialogNoShow(BaseActivity context, final ToastHelper.OnDialogSubmitClickListener listener, int count, int remain, String ss, String title) { | |||
| this.ss = ss; | |||
| AlertDialog.Builder builder = new AlertDialog.Builder(context); | |||
| View view = View.inflate(context, R.layout.dialog_exporting_test_data, (null)); | |||
| mAlertDialog = builder.create(); | |||
| mAlertDialog.setView(view); | |||
| mAlertDialog.setCancelable(false); | |||
| tvContent = view.findViewById(R.id.content); | |||
| String text = (count == 0 && remain == 0) ? (ss + "······") : (ss + "(" + (count - remain) + "/" + count + ")······"); | |||
| tvContent.setText(text); | |||
| ((TextView) (view.findViewById(R.id.title))).setText(title); | |||
| mButton = view.findViewById(R.id.btn_confirm); | |||
| mButton.setOnClickListener((View view2) -> { | |||
| mAlertDialog.dismiss(); | |||
| listener.onOKClickListener(view2); | |||
| }); | |||
| return mAlertDialog; | |||
| } | |||
| public boolean update(Activity activity, final int count, final int remain) { | |||
| if (mAlertDialog == null) { | |||
| return false; | |||
| } | |||
| activity.runOnUiThread(() -> { | |||
| if (tvContent != null) { | |||
| String text = ss + "(" + (count - remain) + "/" + count + ")······"; | |||
| tvContent.setText(text); | |||
| } | |||
| if (mButton != null) { | |||
| mButton.setText(remain == 0 ? R.string.finished : R.string.cancel); | |||
| } | |||
| }); | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,26 @@ | |||
| package com.handset.serialportsensor.view; | |||
| import android.content.Context; | |||
| import android.support.v7.widget.LinearLayoutManager; | |||
| import android.support.v7.widget.RecyclerView; | |||
| import android.view.ViewGroup; | |||
| /** | |||
| * Created by zy on 2019/2/27. | |||
| */ | |||
| public class LinearLayoutManagerCus extends LinearLayoutManager { | |||
| public LinearLayoutManagerCus(Context context) { | |||
| super(context); | |||
| } | |||
| @Override | |||
| public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { | |||
| return super.generateLayoutParams(lp); | |||
| } | |||
| @Override | |||
| public RecyclerView.LayoutParams generateDefaultLayoutParams() { | |||
| return new RecyclerView.LayoutParams((-1), (-2)); | |||
| } | |||
| } | |||
| @ -0,0 +1,379 @@ | |||
| package com.handset.serialportsensor.widget; | |||
| import android.animation.ArgbEvaluator; | |||
| import android.content.Context; | |||
| import android.content.res.TypedArray; | |||
| import android.graphics.Canvas; | |||
| import android.graphics.Color; | |||
| import android.graphics.Paint; | |||
| import android.graphics.RectF; | |||
| import android.text.TextPaint; | |||
| import android.text.TextUtils; | |||
| import android.util.AttributeSet; | |||
| import android.util.Log; | |||
| import android.view.View; | |||
| import com.handset.serialportsensor.R; | |||
| import com.handset.serialportsensor.utils.PixelUtils; | |||
| import java.math.BigDecimal; | |||
| import java.text.DecimalFormat; | |||
| import static android.graphics.Paint.Style.STROKE; | |||
| //@SuppressWarnings(value = "unused") | |||
| public class DashBoard extends View { | |||
| private static final String logTag = "HANDSET-JE002-EX"; | |||
| private Paint paint; | |||
| //最外层圆环的颜色 | |||
| private int circleColor; | |||
| //圆环进度的颜色 | |||
| private int progressCircleColor; | |||
| //圆环的厚度,即大小 | |||
| private float circleThickness; | |||
| //最上面字体的颜色 | |||
| //private int topTextColor; | |||
| //第二行字体的颜色 | |||
| private int secondTextColor; | |||
| //第三行字体的颜色 | |||
| private int thirdTextColor; | |||
| //RoundProgress开始的颜色,决定RoundProgress的渐变区间 | |||
| private int progressStartColor; | |||
| //RoundProgress结束的颜色,决定RoundProgress的渐变区间 | |||
| private int ProgressEndColor; | |||
| //进度的最大值,默认是1000 | |||
| private double maxProgress; | |||
| //当前的进度,默认0 | |||
| private double currentProgress; | |||
| //第二行字 | |||
| private String secondText; | |||
| //第三行字 | |||
| private String thirdText = "kg"; | |||
| //最上面的字的大小 | |||
| //private float topTextSize; | |||
| //第二行字的大小 | |||
| private float secondTextSize; | |||
| //第三行字的大小 | |||
| private float thirdTextSize; | |||
| //最外层圆的半径 | |||
| private int outerFirstCircleRadius; | |||
| //文字颜色是否argb变化 | |||
| private boolean progressArgbColor; | |||
| //小圆是否可用 | |||
| private boolean smallCircleEnable; | |||
| private boolean customArc; | |||
| private int startArc; | |||
| private int center; | |||
| private Float valueFloor; | |||
| private Float valueCeiling; | |||
| private int textPaintStroke; | |||
| private ArgbEvaluator mArgbEvaluator; | |||
| private boolean showOutText; | |||
| protected Paint textStartPaint = new TextPaint(); | |||
| protected Paint textEndPaint = new TextPaint(); | |||
| protected RectF ringRect = new RectF(); | |||
| private float textStartSize; | |||
| private float textEndSize; | |||
| public String textStart; | |||
| public String textEnd; | |||
| private int textStartColor; | |||
| private int textEndColor; | |||
| private Context context; | |||
| private int circlePadding; | |||
| public DashBoard(Context context) { | |||
| this(context, (null)); | |||
| this.context = context; | |||
| } | |||
| public DashBoard(Context context, AttributeSet attrs) { | |||
| this(context, attrs, (0)); | |||
| this.context = context; | |||
| } | |||
| public DashBoard(Context context, AttributeSet attrs, int defStyle) { | |||
| super(context, attrs, defStyle); | |||
| this.context = context; | |||
| paint = new Paint(); | |||
| mArgbEvaluator = new ArgbEvaluator(); | |||
| TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DashBoard); | |||
| //获取自定义属性和默认值 | |||
| circleColor = typedArray.getColor(R.styleable.DashBoard_circleColor, context.getResources().getColor(R.color.dashboard_gray)); | |||
| progressCircleColor = typedArray.getColor(R.styleable.DashBoard_progressCircleColor, context.getResources().getColor(R.color.dashboard_normal_end)); | |||
| progressStartColor = typedArray.getColor(R.styleable.DashBoard_progressStartColor, getResources().getColor(R.color.dashboard_normal_start)); | |||
| ProgressEndColor = typedArray.getColor(R.styleable.DashBoard_progressEndColor, getResources().getColor(R.color.dashboard_normal_end)); | |||
| circleThickness = typedArray.getDimension(R.styleable.DashBoard_circleThickness, PixelUtils.dp2px(context, 10)); | |||
| secondTextColor = typedArray.getColor(R.styleable.DashBoard_secondTextColor, Color.BLACK); | |||
| thirdTextColor = typedArray.getColor(R.styleable.DashBoard_thirdTextColor, Color.BLACK); | |||
| secondText = typedArray.getString(R.styleable.DashBoard_secondText); | |||
| maxProgress = typedArray.getInt(R.styleable.DashBoard_maxProgress, 100); | |||
| currentProgress = typedArray.getInt(R.styleable.DashBoard_currentProgress, 0); | |||
| customArc = typedArray.getBoolean(R.styleable.DashBoard_customArc, false); | |||
| startArc = typedArray.getInt(R.styleable.DashBoard_startArc, 0); | |||
| showOutText = typedArray.getBoolean(R.styleable.DashBoard_showOutText, false); | |||
| textStartSize = typedArray.getDimension(R.styleable.DashBoard_textStartSize, PixelUtils.sp2px(context, 10)); | |||
| textEndSize = typedArray.getDimension(R.styleable.DashBoard_textEndSize, PixelUtils.sp2px(context, 10)); | |||
| textStartColor = typedArray.getColor(R.styleable.DashBoard_textStartColor, context.getResources().getColor(R.color.dashboard_normal_end)); | |||
| textEndColor = typedArray.getColor(R.styleable.DashBoard_textEndColor, context.getResources().getColor(R.color.dashboard_normal_end)); | |||
| textStart = typedArray.getString(R.styleable.DashBoard_textStart); | |||
| textEnd = typedArray.getString(R.styleable.DashBoard_textEnd); | |||
| valueFloor = typedArray.getFloat(R.styleable.DashBoard_valueFloor, (0.0f)); | |||
| valueCeiling = typedArray.getFloat(R.styleable.DashBoard_valueCeiling, (0.0f)); | |||
| //设置第三行文字的默认文字 | |||
| String defaultThirdText = typedArray.getString(R.styleable.DashBoard_thirdText); | |||
| if (defaultThirdText != null) { | |||
| thirdText = defaultThirdText; | |||
| } | |||
| secondTextSize = typedArray.getDimension(R.styleable.DashBoard_secondTextSize, PixelUtils.sp2px(context, 45)); | |||
| thirdTextSize = typedArray.getDimension(R.styleable.DashBoard_thirdTextSize, PixelUtils.sp2px(context, 16)); | |||
| //控制颜色渐变的开关 | |||
| progressArgbColor = typedArray.getBoolean(R.styleable.DashBoard_progressArgbColor, false); | |||
| smallCircleEnable = typedArray.getBoolean(R.styleable.DashBoard_smallCircleEnable, true); | |||
| typedArray.recycle(); | |||
| circlePadding = PixelUtils.dp2px(context, 18); | |||
| } | |||
| @Override | |||
| protected void onDraw(Canvas canvas) { | |||
| super.onDraw(canvas); | |||
| int width = getWidth(); | |||
| int height = getHeight(); | |||
| //第1步:画出最外层的圆环 | |||
| drawOuterFirstCircle(canvas); | |||
| //第2步,画出圆弧 | |||
| drawArc(canvas); | |||
| //第3步,画出三行文字 | |||
| drawText(canvas); | |||
| if (showOutText) { | |||
| textStartPaint.setColor(textStartColor); | |||
| textStartPaint.setTextSize(textStartSize); | |||
| textStartPaint.setAntiAlias(true); | |||
| textEndPaint.setColor(textEndColor); | |||
| textEndPaint.setTextSize(textEndSize); | |||
| textEndPaint.setAntiAlias(true); | |||
| } | |||
| float delta = circleThickness; | |||
| int padding = PixelUtils.dp2px(getContext(), 10); | |||
| ringRect.set(delta + padding, | |||
| delta + padding, | |||
| width - delta - padding, | |||
| height - delta - padding); | |||
| float ringWidth = ringRect.right - ringRect.left; | |||
| //第5步,画出外面的文字 | |||
| if (showOutText && !TextUtils.isEmpty(textStart) && !TextUtils.isEmpty(textEnd)) { | |||
| int endArc = startArc + (int) currentProgress; | |||
| int startPadding = (int) textStartPaint.measureText(textEnd) / 2 + PixelUtils.dp2px(getContext(), 6); | |||
| if (startArc <= 0 || startArc >= 180) { | |||
| startPadding = 0; | |||
| } | |||
| int endPadding = (int) textEndPaint.measureText(textStart) / 3 + PixelUtils.dp2px(getContext(), 2); | |||
| if (endArc > 180) { | |||
| endPadding = 0 - endPadding; | |||
| } | |||
| canvas.drawText(textStart, ringWidth / 2.0f + (ringWidth - circlePadding) / 2 * sin(endArc) + endPadding, ringRect.top + ringWidth / 2 - ringWidth / 2 * cos(endArc), textStartPaint); | |||
| canvas.drawText(textEnd, ringWidth / 2.0f + (ringWidth - circlePadding) / 2 * sin(startArc) + startPadding, ringRect.top + ringWidth / 2 - ringWidth / 2 * cos(startArc), textEndPaint); | |||
| } | |||
| } | |||
| /** | |||
| * 绘制最外层的圆 | |||
| * | |||
| * @param canvas 画笔 | |||
| */ | |||
| private void drawOuterFirstCircle(Canvas canvas) { | |||
| //设置圆的颜色 | |||
| paint.setColor(circleColor); | |||
| //设置只绘制边框 | |||
| paint.setStyle(STROKE); | |||
| //设置圆的宽度 | |||
| paint.setStrokeWidth(circleThickness / 2); | |||
| //消除锯齿 | |||
| paint.setAntiAlias(true); | |||
| //画出圆 | |||
| canvas.drawCircle(center, center, outerFirstCircleRadius, paint); | |||
| } | |||
| private void drawText(Canvas canvas) { | |||
| paint.setStrokeWidth(textPaintStroke); | |||
| paint.setStyle(Paint.Style.FILL); | |||
| //画出第二行文本 | |||
| paint.setTextSize(secondTextSize); | |||
| paint.setColor(secondTextColor); | |||
| float textWidth2 = paint.measureText(secondText); | |||
| canvas.drawText(secondText, center - textWidth2 / 2, center - secondTextSize / 4, paint); //画出卡路里数值 | |||
| //画出第三行文本 | |||
| paint.setTextSize(thirdTextSize); | |||
| paint.setColor(thirdTextColor); | |||
| if (thirdText != null) { | |||
| float textWidth3 = paint.measureText(thirdText); | |||
| canvas.drawText(thirdText, center - textWidth3 / 2, center + (float) outerFirstCircleRadius / 4 + thirdTextSize / 2, paint); //画出卡路里单位 | |||
| } | |||
| } | |||
| private void drawArc(Canvas canvas) { | |||
| paint.setStrokeWidth(circleColor); | |||
| paint.setStyle(STROKE); | |||
| if (smallCircleEnable) { | |||
| paint.setStrokeCap(Paint.Cap.BUTT); | |||
| } else { | |||
| paint.setStrokeCap(Paint.Cap.ROUND); | |||
| } | |||
| paint.setAntiAlias(true); | |||
| //设置圆弧宽度 | |||
| paint.setStrokeWidth(circleThickness + 1); | |||
| RectF oval2 = new RectF(center - outerFirstCircleRadius, center - outerFirstCircleRadius, center + outerFirstCircleRadius, center + outerFirstCircleRadius); //用于定义的圆弧的形状和大小的界限 | |||
| double progress; | |||
| //这里画圆环的时候第二个参数为开始角度,0表示右边中线,90表示底部,-outerFirstCircleRadius | |||
| if (currentProgress < maxProgress) { | |||
| progress = currentProgress; | |||
| drawArcByColor(canvas, oval2, progress); | |||
| } else { | |||
| progress = maxProgress; | |||
| drawArcByColor(canvas, oval2, progress); | |||
| } | |||
| } | |||
| private void drawArcByColor(Canvas canvas, RectF oval2, double progress) { | |||
| for (int i = 0; i < progress / maxProgress * 360; i++) { | |||
| if (progressArgbColor) {//如果颜色渐变, 则改变色值 | |||
| progressCircleColor = (Integer) mArgbEvaluator.evaluate(i / 360f, progressStartColor, ProgressEndColor);//颜色插值器(level 11以上才可以用) | |||
| secondTextColor = ProgressEndColor; | |||
| } | |||
| paint.setAntiAlias(true); | |||
| paint.setColor(progressCircleColor); | |||
| if (customArc) { | |||
| if (i < maxProgress * 360) { | |||
| canvas.drawArc(oval2, (float) (-90 + i + startArc), 1.35f, false, paint); | |||
| } | |||
| } else { | |||
| if (i < maxProgress * 360) { | |||
| canvas.drawArc(oval2, (float) (-90 + i), 1.35f, false, paint); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * 当控件的宽高发生变化的时候调用的方法 | |||
| * 在这里得到控件的宽高,避免在onDraw的时候多次初始化 | |||
| */ | |||
| @Override | |||
| protected void onSizeChanged(int w, int h, int oldw, int oldh) { | |||
| super.onSizeChanged(w, h, oldw, oldh); | |||
| //获取圆心的坐标,对于自身控件而言是1/2 | |||
| center = getMeasuredWidth() / 2; | |||
| //原本是半径是等于中心点,但是由于设置画笔宽度的时候,这个宽度会根据当前的半径,往外部和内部各扩展1/2。 | |||
| //所以在设置半径是需要减去圆环宽度的一半。 | |||
| //这里减去整个圆环厚度是因为想让圆环距离本控件有左右间距,故意为之 | |||
| outerFirstCircleRadius = (int) (center - circleThickness - PixelUtils.dp2px(context, 18)); | |||
| //文字不用太大 | |||
| textPaintStroke = 1; | |||
| } | |||
| public float sin(int i) { | |||
| return (float) Math.sin(i * Math.PI / 180); | |||
| } | |||
| public float cos(int i) { | |||
| return (float) Math.cos(i * Math.PI / 180); | |||
| } | |||
| public void setTextStart(String textStart) { | |||
| this.textStart = textStart; | |||
| this.invalidate(); | |||
| } | |||
| public void setTextEnd(String textEnd) { | |||
| this.textEnd = textEnd; | |||
| this.invalidate(); | |||
| } | |||
| private final static String FLOAT_TYPE = "0.00"; | |||
| public void setSecondText(Float value) { | |||
| BigDecimal tmp = new BigDecimal(value); | |||
| BigDecimal floor = new BigDecimal(valueFloor); | |||
| BigDecimal ceiling = new BigDecimal(valueCeiling); | |||
| if (!(tmp.compareTo(floor) < 0 || tmp.compareTo(ceiling) > 0)) { | |||
| this.secondText = new DecimalFormat(FLOAT_TYPE).format(value); | |||
| invalidate(); | |||
| return; | |||
| } | |||
| Log.w(logTag, ("item: " + thirdText + ", value: " + value + " exceed!")); | |||
| } | |||
| public void setSecondText(Float value, boolean isNormal) { | |||
| Log.i(logTag, "value: " + value); | |||
| BigDecimal tmp = new BigDecimal(value); | |||
| BigDecimal floor = new BigDecimal(valueFloor); | |||
| BigDecimal ceiling = new BigDecimal(valueCeiling); | |||
| if (!(tmp.compareTo(floor) < 0 || tmp.compareTo(ceiling) > 0)) { | |||
| this.secondText = new DecimalFormat(FLOAT_TYPE).format(value); | |||
| setProgressStartColor(getResources().getColor(isNormal ? R.color.progress_normal_start : R.color.progress_err_end)); | |||
| setProgressEndColor(getResources().getColor(isNormal ? R.color.progress_normal_end : R.color.progress_err_end)); | |||
| invalidate(); | |||
| return; | |||
| } | |||
| Log.w(logTag, ("item: " + thirdText + ", value: " + value + " exceed!")); | |||
| } | |||
| public void setSecondText(String value) { | |||
| this.secondText = value; | |||
| setProgressStartColor(getResources().getColor(R.color.progress_normal_start)); | |||
| setProgressEndColor(getResources().getColor( R.color.progress_normal_end )); | |||
| invalidate(); | |||
| } | |||
| /** | |||
| * 控制RoundProgress颜色渐变 | |||
| * @param progressCircleColor startColor | |||
| */ | |||
| public void setProgressStartColor(int progressCircleColor) { | |||
| this.progressStartColor = progressCircleColor; | |||
| } | |||
| /** | |||
| * 控制RoundProgress颜色渐变 | |||
| * @param progressCircleColor endColor | |||
| */ | |||
| public void setProgressEndColor(int progressCircleColor) { | |||
| this.ProgressEndColor = progressCircleColor; | |||
| } | |||
| } | |||
| @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <rotate xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:duration="1000" | |||
| android:fromDegrees="0" | |||
| android:pivotX="50%" | |||
| android:pivotY="50%" | |||
| android:repeatCount="-1" | |||
| android:toDegrees="360"> | |||
| </rotate> | |||
| @ -0,0 +1,34 @@ | |||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | |||
| xmlns:aapt="http://schemas.android.com/aapt" | |||
| android:height="108dp" | |||
| android:viewportHeight="108" | |||
| android:viewportWidth="108" | |||
| android:width="108dp"> | |||
| <path | |||
| android:fillType="evenOdd" | |||
| android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z" | |||
| android:strokeColor="#00000000" | |||
| android:strokeWidth="1"> | |||
| <aapt:attr name="android:fillColor"> | |||
| <gradient | |||
| android:endX="78.5885" | |||
| android:endY="90.9159" | |||
| android:startX="48.7653" | |||
| android:startY="61.0927" | |||
| 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="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z" | |||
| android:strokeColor="#00000000" | |||
| android:strokeWidth="1"/> | |||
| </vector> | |||
| @ -0,0 +1,7 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <solid android:color="#ff0000"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <!--<padding--> | |||
| <!--android:left="16dp"--> | |||
| <!--android:top="2dp"--> | |||
| <!--android:right="16dp"--> | |||
| <!--android:bottom="2dp"/><!– 各方向的间隔 –>--> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="@android:color/white"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp" | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <!--<padding--> | |||
| <!--android:left="16dp"--> | |||
| <!--android:top="2dp"--> | |||
| <!--android:right="16dp"--> | |||
| <!--android:bottom="2dp"/><!– 各方向的间隔 –>--> | |||
| <stroke | |||
| android:width="1px" | |||
| android:color="#999999"/> | |||
| <solid android:color="@color/white"/> | |||
| </shape> | |||
| @ -0,0 +1,18 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp" | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" /><!-- 设置圆角半径 --> | |||
| <size | |||
| android:width="120dp" | |||
| android:height="120dp" /> | |||
| <!-- 填充 --> | |||
| <solid android:color="@android:color/white" /><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,5 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <corners android:radius="10dp"></corners> | |||
| <solid android:color="@android:color/white"/> | |||
| </shape> | |||
| @ -0,0 +1,19 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="20dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <padding | |||
| android:left="2dp" | |||
| android:top="2dp" | |||
| android:right="2dp" | |||
| android:bottom="2dp"/><!-- 各方向的间隔 --> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="@color/status_green"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <padding | |||
| android:left="2dp" | |||
| android:top="2dp" | |||
| android:right="2dp" | |||
| android:bottom="2dp"/><!-- 各方向的间隔 --> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="#5a9ecd"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,19 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="20dp" /><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <padding | |||
| android:left="2dp" | |||
| android:top="2dp" | |||
| android:right="2dp" | |||
| android:bottom="2dp"/><!-- 各方向的间隔 --> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="@color/primaryBlue"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <padding | |||
| android:left="2dp" | |||
| android:top="2dp" | |||
| android:right="2dp" | |||
| android:bottom="2dp"/><!-- 各方向的间隔 --> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="#9d9d9d"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,19 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="20dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <padding | |||
| android:left="2dp" | |||
| android:top="2dp" | |||
| android:right="2dp" | |||
| android:bottom="2dp"/><!-- 各方向的间隔 --> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="@color/progress_err_end"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <item android:drawable="@mipmap/ic_dout_abnormal" android:state_checked="true" /> | |||
| <item android:drawable="@mipmap/cb_unselect" android:state_checked="false" /> | |||
| <item android:drawable="@mipmap/cb_unselect" /> | |||
| </selector> | |||
| @ -0,0 +1,6 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <item android:drawable="@mipmap/ic_dout_normal" android:state_checked="true" /> | |||
| <item android:drawable="@mipmap/cb_unselect" android:state_checked="false" /> | |||
| <item android:drawable="@mipmap/cb_unselect" /> | |||
| </selector> | |||
| @ -0,0 +1,23 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="9dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp"/><!-- 设置圆角半径 --> | |||
| <!-- 间隔 --> | |||
| <!--<padding--> | |||
| <!--android:left="16dp"--> | |||
| <!--android:top="2dp"--> | |||
| <!--android:right="16dp"--> | |||
| <!--android:bottom="2dp"/><!– 各方向的间隔 –>--> | |||
| <!-- 填充 --> | |||
| <solid | |||
| android:color="#e3e3e3"/><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,171 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <vector | |||
| xmlns:android="http://schemas.android.com/apk/res/android" | |||
| android:height="108dp" | |||
| android:viewportHeight="108" | |||
| android:viewportWidth="108" | |||
| android:width="108dp"> | |||
| <path | |||
| android:fillColor="#26A69A" | |||
| android:pathData="M0,0h108v108h-108z"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M9,0L9,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,0L19,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M29,0L29,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M39,0L39,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M49,0L49,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M59,0L59,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M69,0L69,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M79,0L79,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M89,0L89,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M99,0L99,108" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,9L108,9" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,19L108,19" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,29L108,29" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,39L108,39" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,49L108,49" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,59L108,59" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,69L108,69" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,79L108,79" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,89L108,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M0,99L108,99" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,29L89,29" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,39L89,39" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,49L89,49" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,59L89,59" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,69L89,69" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M19,79L89,79" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M29,19L29,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M39,19L39,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M49,19L49,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M59,19L59,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M69,19L69,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| <path | |||
| android:fillColor="#00000000" | |||
| android:pathData="M79,19L79,89" | |||
| android:strokeColor="#33FFFFFF" | |||
| android:strokeWidth="0.8"/> | |||
| </vector> | |||
| @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="19dp"/><!-- 设置圆角半径 --> | |||
| <stroke | |||
| android:width="1px" | |||
| android:color="@color/white"/> | |||
| </shape> | |||
| @ -0,0 +1,9 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:radius="5dp"/><!-- 设置圆角半径 --> | |||
| <solid android:color="@color/white"/> | |||
| </shape> | |||
| @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" /><!-- 设置圆角半径 --> | |||
| <solid android:color="#5a2b2b2d" /><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,12 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <!-- 圆角 --> | |||
| <corners | |||
| android:bottomLeftRadius="5dp" | |||
| android:bottomRightRadius="5dp" | |||
| android:topLeftRadius="5dp" | |||
| android:topRightRadius="5dp" /><!-- 设置圆角半径 --> | |||
| <solid android:color="@color/gray_bg" /><!-- 填充的颜色 --> | |||
| </shape> | |||
| @ -0,0 +1,33 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <!-- | |||
| Copyright 2012 GitHub Inc. | |||
| 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 | |||
| http://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. | |||
| --> | |||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > | |||
| <item> | |||
| <rotate | |||
| android:fromDegrees="0" | |||
| android:interpolator="@android:anim/linear_interpolator" | |||
| android:pivotX="50%" | |||
| android:pivotY="50%" | |||
| android:toDegrees="360" > | |||
| <bitmap | |||
| android:antialias="true" | |||
| android:filter="true" | |||
| android:src="@drawable/loading" /> | |||
| </rotate> | |||
| </item> | |||
| </layer-list> | |||
| @ -0,0 +1,14 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <item | |||
| android:id="@+id/background" | |||
| android:drawable="@mipmap/seekbar_gray"></item> | |||
| <item android:id="@+id/background_01"> | |||
| <scale android:drawable="@mipmap/seekbar_gray" /> | |||
| </item> | |||
| <item android:id="@+id/background_02"> | |||
| <scale android:drawable="@mipmap/seekbar_gray" /> | |||
| </item> | |||
| </layer-list> | |||
| @ -0,0 +1,14 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <item | |||
| android:id="@+id/background" | |||
| android:drawable="@mipmap/seekbar_blue"></item> | |||
| <item android:id="@+id/background_01"> | |||
| <scale android:drawable="@mipmap/seekbar_blue" /> | |||
| </item> | |||
| <item android:id="@+id/background_02"> | |||
| <scale android:drawable="@mipmap/seekbar_blue" /> | |||
| </item> | |||
| </layer-list> | |||