From: kfl_614 Date: Sun, 22 Mar 2020 10:44:59 +0000 (+0800) Subject: 1.服务APP,主要包含对天气。计步,血压的处理。此服务长期存在在后台。由Launcher启动或者开机启动。 X-Git-Url: http://git.snicker.com.cn/Users/apple/Desktop/static/gitweb.js?a=commitdiff_plain;h=78be752b6b85fb1adcf85e650e17c01accfc30cd;p=icworkservice.git 1.服务APP,主要包含对天气。计步,血压的处理。此服务长期存在在后台。由Launcher启动或者开机启动。 --- 78be752b6b85fb1adcf85e650e17c01accfc30cd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..681f41a --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,116 @@ + + + + + + + +
+ + + + xmlns:android + + ^$ + + + +
+
+ + + + xmlns:.* + + ^$ + + + BY_NAME + +
+
+ + + + .*:id + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + .*:name + + http://schemas.android.com/apk/res/android + + + +
+
+ + + + name + + ^$ + + + +
+
+ + + + style + + ^$ + + + +
+
+ + + + .* + + ^$ + + + BY_NAME + +
+
+ + + + .* + + http://schemas.android.com/apk/res/android + + + ANDROID_ATTRIBUTE_ORDER + +
+
+ + + + .* + + .* + + + BY_NAME + +
+
+
+
+
+
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..d291b3d --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..7bfef59 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..1711e9b --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/EQC_G5.jks b/app/EQC_G5.jks new file mode 100644 index 0000000..2229d46 Binary files /dev/null and b/app/EQC_G5.jks differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..50ef5d6 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,82 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + defaultConfig { + applicationId "com.ic.work" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + //使用JDK1.8 + compileOptions { + targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_1_8 + } + + + sourceSets { + main { + jni.srcDirs = [] + manifest.srcFile 'src/main/AndroidManifest.xml' + java.srcDirs = ['src/main/java', 'src/main/aidl'] + resources.srcDirs = ['src/main/java', 'src/main/aidl'] + aidl.srcDirs = ['src/main/aidl'] + res.srcDirs = ['src/main/res'] + assets.srcDirs = ['src/main/assets'] + } + } + + signingConfigs { + key { + storeFile file("EQC_G5.jks") + storePassword "123456" + keyAlias "watch_g5" + keyPassword "123456" + } + } + + buildTypes { + release { + zipAlignEnabled true // zip 对齐优化 + shrinkResources true // 移除未使用的资源文件 + signingConfig signingConfigs.key + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + renderscriptDebuggable = false + debuggable = false + jniDebuggable = false + manifestPlaceholders = [:] + } + + debug { + signingConfig signingConfigs.key + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + implementation 'com.amap.api:location:4.8.0' + + implementation 'org.greenrobot:eventbus:3.2.0' + + implementation 'com.squareup.okio:okio:2.4.3' + + implementation 'com.alibaba:fastjson:1.2.61' + + implementation "androidx.room:room-runtime:2.2.5" + annotationProcessor "androidx.room:room-compiler:2.2.5" + + implementation 'com.jakewharton.threetenabp:threetenabp:1.2.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/ic/work/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/ic/work/ExampleInstrumentedTest.java new file mode 100644 index 0000000..03d098b --- /dev/null +++ b/app/src/androidTest/java/com/ic/work/ExampleInstrumentedTest.java @@ -0,0 +1,27 @@ +package com.ic.work; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + + assertEquals("com.ic.work", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c017541 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/blood/BloodState.java b/app/src/main/aidl/com/ic/aidl/blood/BloodState.java new file mode 100644 index 0000000..82ed7f7 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/BloodState.java @@ -0,0 +1,16 @@ +package com.ic.aidl.blood; + +public class BloodState { + + public static final int BLOOD_NULL_TIPS = -1; + public static final int BLOOD_NOT_DEVICE = 1001; + + public static final int BLOOD_PLEASE_QUIET = 1002; + public static final int BLOOD_START_CHECK= 1003; + + public static final int BLOOD_NOT_WEAR=1004; + public static final int BLOOD_ING_CHECK=1005; + + public static final int BLOOD_STOP_CHECK=1006; + public static final int BLOOD_NOT_DATA_CHECK=1007; +} diff --git a/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl new file mode 100644 index 0000000..092c192 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/IBloodAidlInterface.aidl @@ -0,0 +1,14 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.blood; + +// Declare any non-default types here with import statements + +interface IBloodAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + + void updateBloodCheckResult(int high,int low,int heart); + void updateBloodCheckTips(int top,int bottom); +} diff --git a/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl new file mode 100644 index 0000000..00546c2 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/blood/IBloodRemoteService.aidl @@ -0,0 +1,18 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.blood; + +// Declare any non-default types here with import statements + +import com.ic.aidl.blood.IBloodAidlInterface; + +interface IBloodRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IBloodAidlInterface cb); + void unregisterCallback(IBloodAidlInterface cb); + + void startCheckBlood(); + void stopCheckBlood(); +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl new file mode 100644 index 0000000..b9615f6 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/IPedAidlInterface.aidl @@ -0,0 +1,15 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.ped; + +// Declare any non-default types here with import statements +import com.ic.aidl.ped.RecordParcelable; + +interface IPedAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void updatePedCount(int count); + void updatePedRecord(in List record); + +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl new file mode 100644 index 0000000..60b57a3 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/IPedRemoteService.aidl @@ -0,0 +1,20 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.ped; + +// Declare any non-default types here with import statements + +import com.ic.aidl.ped.IPedAidlInterface; + +interface IPedRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IPedAidlInterface cb); + void unregisterCallback(IPedAidlInterface cb); + + void queryPedCount(); + void queryPedRecord(); + void syncPedHeightSetting(int height); + void syncPedWeightSetting(int weight); +} diff --git a/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl new file mode 100644 index 0000000..7f54af8 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.aidl @@ -0,0 +1,3 @@ +package com.ic.aidl.ped; + +parcelable RecordParcelable; \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java new file mode 100644 index 0000000..bcdef77 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/ped/RecordParcelable.java @@ -0,0 +1,88 @@ +package com.ic.aidl.ped; + +import android.os.Parcel; +import android.os.Parcelable; + +public class RecordParcelable implements Parcelable { + private int number; + private String distance; + private String calorie; + private String date; + + public RecordParcelable() { + number = 0; + distance = null; + calorie = null; + date = ""; + } + + public RecordParcelable(int number, String distance, String calorie, String date) { + this.number = number; + this.distance = distance; + this.calorie = calorie; + this.date = date; + } + + public RecordParcelable(Parcel p) { + this.number = p.readInt(); + this.distance = p.readString(); + this.calorie = p.readString(); + this.date = p.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(number); + dest.writeString(distance); + dest.writeString(calorie); + dest.writeString(date); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public RecordParcelable createFromParcel(Parcel in) { + return new RecordParcelable(in); + } + + public RecordParcelable[] newArray(int size) { + return new RecordParcelable[size]; + } + }; + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public String getDistance() { + return distance; + } + + public void setDistance(String distance) { + this.distance = distance; + } + + public String getCalorie() { + return calorie; + } + + public void setCalorie(String calorie) { + this.calorie = calorie; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl b/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl new file mode 100644 index 0000000..219c69e --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/IWeatherAidlInterface.aidl @@ -0,0 +1,14 @@ +// IWeatherAidlInterface.aidl +package com.ic.aidl.weather; + +// Declare any non-default types here with import statements +import com.ic.aidl.weather.WeatherParcelable; + +interface IWeatherAidlInterface { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void updateCurrWeather(in WeatherParcelable weather); + +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl b/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl new file mode 100644 index 0000000..2f33b2b --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/IWeatherRemoteService.aidl @@ -0,0 +1,17 @@ +// IWeatherRemoteService.aidl +package com.ic.aidl.weather; + +// Declare any non-default types here with import statements + +import com.ic.aidl.weather.IWeatherAidlInterface; + +interface IWeatherRemoteService { + /** + * Demonstrates some basic types that you can use as parameters + * and return values in AIDL. + */ + void registerCallback(IWeatherAidlInterface cb); + void unregisterCallback(IWeatherAidlInterface cb); + + void queryWeatherInfo(); +} diff --git a/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl new file mode 100644 index 0000000..59b6fd3 --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.aidl @@ -0,0 +1,3 @@ +package com.ic.aidl.weather; + +parcelable WeatherParcelable; \ No newline at end of file diff --git a/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java new file mode 100644 index 0000000..e7c9bbb --- /dev/null +++ b/app/src/main/aidl/com/ic/aidl/weather/WeatherParcelable.java @@ -0,0 +1,144 @@ +package com.ic.aidl.weather; + +import android.os.Parcel; +import android.os.Parcelable; + +public class WeatherParcelable implements Parcelable { + private String city; + private String statusDay; // 白天状态,如:晴 + private String statusNight; // 晚上状态 + private String figureDay; // 状态索引 + private String figureNight; + private String temperatureDay; // 白天温度 或 最低温度 + private String temperatureNight; // 晚上温度 或 最低温度 + private String updateTime; // 更新时间 + + public WeatherParcelable() { + city = ""; + statusDay = ""; + statusNight = ""; + figureDay = ""; + figureNight = ""; + temperatureDay = ""; + temperatureNight = ""; + updateTime = ""; + } + + public WeatherParcelable(String city, + String statusDay, String statusNight, + String figureDay, String figureNight, + String temperatureDay, String temperatureNight, + String updateTime) { + this.city = city; + this.statusDay = statusDay; + this.statusNight = statusNight; + this.figureDay = figureDay; + this.figureNight =figureNight; + this.temperatureDay = temperatureDay; + this.temperatureNight = temperatureNight; + this.updateTime =updateTime; + } + + public WeatherParcelable(Parcel p) { + this.city = p.readString(); + this.statusDay = p.readString(); + this.statusNight = p.readString(); + this.figureDay = p.readString(); + this.figureNight = p.readString(); + this.temperatureDay = p.readString(); + this.temperatureNight = p.readString(); + this.updateTime = p.readString(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(city); + dest.writeString(statusDay); + dest.writeString(statusNight); + dest.writeString(figureDay); + dest.writeString(figureNight); + dest.writeString(temperatureDay); + dest.writeString(temperatureNight); + dest.writeString(updateTime); + } + + public static final Creator CREATOR + = new Creator() { + public WeatherParcelable createFromParcel(Parcel in) { + return new WeatherParcelable(in); + } + + public WeatherParcelable[] newArray(int size) { + return new WeatherParcelable[size]; + } + }; + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStatusDay() { + return statusDay; + } + + public void setStatusDay(String statusDay) { + this.statusDay = statusDay; + } + + public String getStatusNight() { + return statusNight; + } + + public void setStatusNight(String statusNight) { + this.statusNight = statusNight; + } + + public String getFigureDay() { + return figureDay; + } + + public void setFigureDay(String figureDay) { + this.figureDay = figureDay; + } + + public String getFigureNight() { + return figureNight; + } + + public void setFigureNight(String figureNight) { + this.figureNight = figureNight; + } + + public String getTemperatureDay() { + return temperatureDay; + } + + public void setTemperatureDay(String temperatureDay) { + this.temperatureDay = temperatureDay; + } + + public String getTemperatureNight() { + return temperatureNight; + } + + public void setTemperatureNight(String temperatureNight) { + this.temperatureNight = temperatureNight; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } +} diff --git a/app/src/main/java/com/ic/jni/ICJniUtils.java b/app/src/main/java/com/ic/jni/ICJniUtils.java new file mode 100644 index 0000000..cb2aac2 --- /dev/null +++ b/app/src/main/java/com/ic/jni/ICJniUtils.java @@ -0,0 +1,60 @@ +package com.ic.jni; + + +public class ICJniUtils { + + public ICJniUtils(){ + + } + + static { + System.loadLibrary("ICJniUtils"); + } + + /***************计步控制************************************/ + /*运行此函数清除 系统计步为0*/ + public static native int resetStepCount(); + + /*获取当前步数*/ + public static native int getStepCount(); + /*开启计步 不必判断返回值*/ + public static native int enablePedometer(); + /*停止计步 不必判断返回值*/ + public static native int disablePedometer(); + + /*检测计步当前是否开启 1开启,0 关闭*/ + public static native int isPedometerEnabled(); + + /*保存当前步数(getStepCount取得的值)到磁盘 不必判断返回值*/ + public static native int saveStepCount(); + + /*恢复保存时的步数数据,下次getStepCount会在恢复的值上增加 不必判断返回值*/ + public static native int recoverStepCount(); + + + /******心率,血压****************************************/ + /*检查 PPG硬件是否存在,返回 1 存在,0 不存在*/ + public static native int isPPGavailable(); + + /*开启心率血压检测*/ + public static native int enablePPG(); + + /*停止心率血压检测*/ + public static native int disablePPG(); + /*返回 心率值 每分钟跳动次数, 通过这个心率>0 判断是否已经有检测结果, + 有就可以直接通过getHighBloodPressure 和 getLowBloodPressure 获取血压高压低压值*/ + public static native int getPPG(); + /* 返回PPG 运行状态, 0 停止, 1,运行中*/ + public static native int isPPGStarted(); + /*返回是否佩戴 0 未佩戴,1 佩戴*/ + public static native int isWeared(); + + /*获取血压高压值*/ + public static native int getHighBloodPressure(); + + /*获取血压低压值*/ + public static native int getLowBloodPressure(); + + /*获取血氧值*/ + public static native int getSPO2(); +} diff --git a/app/src/main/java/com/ic/work/MainActivity.java b/app/src/main/java/com/ic/work/MainActivity.java new file mode 100644 index 0000000..691fc01 --- /dev/null +++ b/app/src/main/java/com/ic/work/MainActivity.java @@ -0,0 +1,40 @@ +package com.ic.work; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; +import android.widget.Button; + +import com.ic.work.utils.IcLog; +import com.ic.work.utils.PedUtil; +import com.ic.work.utils.ServiceUtil; + +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; + +import java.math.BigDecimal; + +public class MainActivity extends AppCompatActivity { + private static final String TAG="MainActivity"; + + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Button mBt = (Button) findViewById(R.id.start_service_bt); + mBt.setOnClickListener(view -> { + ServiceUtil.startServiceUtil(getApplicationContext(), + "com.ic.action.WORK_SERVICE", + getPackageName()); + }); + + OffsetDateTime today = OffsetDateTime.now(); + IcLog.i(TAG,today.format(formatter)); + + BigDecimal bg = new BigDecimal(PedUtil.calcDistanceBySteps(170, 1000)); + IcLog.i(TAG,""+bg.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue()); + } +} diff --git a/app/src/main/java/com/ic/work/ThreadPoolManager.java b/app/src/main/java/com/ic/work/ThreadPoolManager.java new file mode 100644 index 0000000..8a5486e --- /dev/null +++ b/app/src/main/java/com/ic/work/ThreadPoolManager.java @@ -0,0 +1,46 @@ +package com.ic.work; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPoolManager { + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); + + private static ThreadPoolManager mInstance; + + private ThreadPoolExecutor mTheadPool; + + public static final synchronized ThreadPoolManager getInstance() { + if (mInstance == null) { + mInstance = new ThreadPoolManager(); + } + return mInstance; + } + + private ThreadPoolManager() { + mTheadPool = new ThreadPoolExecutor( + 0, + CPU_COUNT * 2 + 1, + 120L, TimeUnit.SECONDS, + new SynchronousQueue()); + } + + public void execute(Runnable runnable) { + if (runnable == null) + return; + + mTheadPool.execute(runnable); + } + + /** + * 从线程池中移除任务 + */ + public void remove(Runnable runnable) { + if (runnable == null) + return; + + mTheadPool.remove(runnable); + } +} diff --git a/app/src/main/java/com/ic/work/WorkService.java b/app/src/main/java/com/ic/work/WorkService.java new file mode 100644 index 0000000..1a1fdb4 --- /dev/null +++ b/app/src/main/java/com/ic/work/WorkService.java @@ -0,0 +1,187 @@ +package com.ic.work; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +import com.ic.work.event.BloodCheckResultEvent; +import com.ic.work.event.BloodCheckTipsEvent; +import com.ic.work.event.LocationResultEvent; +import com.ic.work.event.PedCountEvent; +import com.ic.work.event.PedRecordResultEvent; +import com.ic.work.event.PedSettingEvent; +import com.ic.work.event.WeatherAgainEvent; +import com.ic.work.event.WeatherResultEvent; +import com.ic.work.process.BloodProcess; +import com.ic.work.process.PedProcess; +import com.ic.work.process.WeatherProcess; +import com.ic.work.utils.IcLog; +import com.ic.work.utils.SPUtils; +import com.ic.work.weather.WeatherHelper; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +public class WorkService extends Service { + + private static final String TAG = "WorkService"; + + private WeatherProcess weatherProcess; + private BloodProcess bloodProcess; + private PedProcess pedProcess; + + private WeatherHelper mWeatherHelper; + + private WorkServiceApp mApp; + + @Override + public IBinder onBind(Intent intent) { + if (intent != null) { + int reqType = intent.getIntExtra("REQ_TYPE", -1); + IcLog.i(TAG,"Bind reqType"+reqType); + switch (reqType) { + case 101: + //天气 + return weatherProcess.getWeatherBinder(); + case 102: + //血压 + return bloodProcess.getBloodBinder(); + case 103: + //计步 + return pedProcess.getPedBinder(); + default: + return null; + } + } + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + mApp = (WorkServiceApp) getApplication(); + + weatherProcess = new WeatherProcess(mApp); + bloodProcess = new BloodProcess(); + + pedProcess = new PedProcess( + (WorkServiceApp) getApplication(), + SPUtils.getPedHeightSP(getApplicationContext()), + SPUtils.getPedWighttSP(getApplicationContext())); + + mWeatherHelper = new WeatherHelper(); + + EventBus.getDefault().register(this); + + mWeatherHelper.startLocation(getApplicationContext()); + + IcLog.i(TAG, "work service is start"); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + IcLog.i(TAG,"WorkService onStartCommand"); + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + super.onDestroy(); + IcLog.i(TAG,"WorkService onDestroy"); + bloodProcess = null; + + mApp = null; + EventBus.getDefault().unregister(this); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(LocationResultEvent event) { + mWeatherHelper.queryWeatherServerInfo(mApp.getWeatherRepository(),event.getmCity()); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(BloodCheckTipsEvent event) { + if (bloodProcess != null) { + bloodProcess.sendBloodCheckTips(event.getTopTips(), + event.getBottomTips()); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(BloodCheckResultEvent event) { + if (bloodProcess != null) { + bloodProcess.sendBloodCheckResult(event.getHigh(), + event.getLow(), event.getHeart()); + } + + //发送一次广播给 心率 launcher + sendHeartBroadcast(event.getHeart()); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(PedSettingEvent event) { + + if(pedProcess != null){ + return; + } + + switch (event.getType()){ + case 1: + int height = event.getValue(); + SPUtils.setPedHeightSP(getApplicationContext(),height); + pedProcess.updateHeight(height); + break; + case 2: + int weight = event.getValue(); + SPUtils.setPedWighttSP(getApplicationContext(),weight); + pedProcess.updateWeight(weight); + break; + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(PedRecordResultEvent event) { + if(pedProcess != null){ + pedProcess.sendPedRecord(event.getRecordList()); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(PedCountEvent event) { + if(pedProcess != null){ + pedProcess.sendPedCount(event.getPedCount()); + } + + //发送一次广播给launcher + sendPedCountBroadcast(event.getPedCount()); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(WeatherResultEvent event) { + if(weatherProcess != null){ + weatherProcess.sendCurrWeather(event.getParcelable()); + } + } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMessageEvent(WeatherAgainEvent event) { + if(mWeatherHelper != null){ + mWeatherHelper.startLocation(getApplicationContext()); + } + } + + private void sendPedCountBroadcast(int count){ + Intent pedIntent = new Intent(); + pedIntent.setAction("com.ic.action.PED_COUNT"); + pedIntent.putExtra("PED_COUNT",count); + sendBroadcast(pedIntent); + } + + private void sendHeartBroadcast(int count){ + Intent pedIntent = new Intent(); + pedIntent.setAction("com.ic.action.BLOOD_HEART"); + pedIntent.putExtra("BLOOD_HEART",count); + sendBroadcast(pedIntent); + } + +} diff --git a/app/src/main/java/com/ic/work/WorkServiceApp.java b/app/src/main/java/com/ic/work/WorkServiceApp.java new file mode 100644 index 0000000..2c9af47 --- /dev/null +++ b/app/src/main/java/com/ic/work/WorkServiceApp.java @@ -0,0 +1,32 @@ +package com.ic.work; + +import android.app.Application; + +import com.ic.work.db.AppDatabase; +import com.ic.work.db.PedInjection; +import com.ic.work.db.WeatherInjection; +import com.ic.work.utils.IcLog; +import com.jakewharton.threetenabp.AndroidThreeTen; + +public class WorkServiceApp extends Application { + + @Override + public void onCreate() { + super.onCreate(); + IcLog.setLogHead("IcWorkService"); + + AndroidThreeTen.init(this); + } + + public AppDatabase getDatabase() { + return AppDatabase.getInstance(this); + } + + public PedInjection getRepository() { + return PedInjection.getInstance(getDatabase()); + } + + public WeatherInjection getWeatherRepository() { + return WeatherInjection.getInstance(getDatabase()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ic/work/db/AppDatabase.java b/app/src/main/java/com/ic/work/db/AppDatabase.java new file mode 100644 index 0000000..3ada192 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/AppDatabase.java @@ -0,0 +1,40 @@ +package com.ic.work.db; + +import android.content.Context; + +import androidx.room.Database; +import androidx.room.Room; +import androidx.room.RoomDatabase; +import androidx.room.TypeConverters; + +import com.ic.work.db.dao.PedDao; +import com.ic.work.db.dao.WeatherDao; +import com.ic.work.db.entity.PedEntity; +import com.ic.work.db.entity.WeatherEntity; + +@Database(entities = {PedEntity.class, WeatherEntity.class}, version = 2,exportSchema = false) +@TypeConverters(TiviTypeConverters.class) +public abstract class AppDatabase extends RoomDatabase { + + private static AppDatabase sInstance; + + public static final String DATABASE_NAME = "ic-work-db"; + + public abstract PedDao loadPedDao(); + public abstract WeatherDao loadWeatherDao(); + + public static AppDatabase getInstance(final Context context) { + if (sInstance == null) { + synchronized (AppDatabase.class) { + if (sInstance == null) { + sInstance = buildDatabase(context.getApplicationContext()); + } + } + } + return sInstance; + } + + private static AppDatabase buildDatabase(final Context appContext) { + return Room.databaseBuilder(appContext, AppDatabase.class, DATABASE_NAME).build(); + } +} diff --git a/app/src/main/java/com/ic/work/db/PedInjection.java b/app/src/main/java/com/ic/work/db/PedInjection.java new file mode 100644 index 0000000..a0254a3 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/PedInjection.java @@ -0,0 +1,69 @@ +package com.ic.work.db; + +import android.content.Context; + +import com.ic.work.db.dao.PedDao; +import com.ic.work.db.entity.PedEntity; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; + +import java.util.Date; +import java.util.List; + +public class PedInjection { + + private static PedInjection sInstance; + + private final AppDatabase mDatabase; + + private PedInjection(final AppDatabase database) { + mDatabase = database; + } + + public static PedInjection getInstance(final AppDatabase database) { + if (sInstance == null) { + synchronized (PedInjection.class) { + if (sInstance == null) { + sInstance = new PedInjection(database); + } + } + } + return sInstance; + } + + private PedDao getPedDao() { + return mDatabase.loadPedDao(); + } + + public List queryDBPedDate(LocalDate date) { + return getPedDao().loadDatePedList(date); + } + + public void insertDBPedDate(PedEntity entity) { + getPedDao().insertPedEntity(entity); + } + + public void updateDBPedDate(PedEntity entity) { + getPedDao().updatePedEntity(entity.getId(), + entity.getPedNumber(), + entity.getPedDistance(), + entity.getPedDistance()); + } + + public int queryDBPedCount() { + return getPedDao().queryCountPed(); + } + + public List queryDBPedAllList() { + return getPedDao().loadAllDatePedList(); + } + + public List queryDBPedOldestList() { + return getPedDao().loadOldestDatePedList(); + } + + public void deletePedEntity(int id) { + getPedDao().deletePedEntity(id); + } +} diff --git a/app/src/main/java/com/ic/work/db/TiviTypeConverters.java b/app/src/main/java/com/ic/work/db/TiviTypeConverters.java new file mode 100644 index 0000000..63207d0 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/TiviTypeConverters.java @@ -0,0 +1,29 @@ +package com.ic.work.db; + +import android.text.TextUtils; + +import androidx.room.TypeConverter; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.format.DateTimeFormatter; + +public class TiviTypeConverters { + + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + + @TypeConverter + public static LocalDate toLocalDate(String value) { + if (TextUtils.isEmpty(value)) { + return null; + } + return formatter.parse(value,LocalDate.FROM); + } + + @TypeConverter + public static String fromLocalDate(LocalDate date) { + if (date == null) { + return null; + } + return date.format(formatter); + } +} diff --git a/app/src/main/java/com/ic/work/db/WeatherInjection.java b/app/src/main/java/com/ic/work/db/WeatherInjection.java new file mode 100644 index 0000000..a990d86 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/WeatherInjection.java @@ -0,0 +1,47 @@ +package com.ic.work.db; + +import com.ic.work.db.dao.WeatherDao; +import com.ic.work.db.entity.WeatherEntity; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; + +import java.util.List; + +public class WeatherInjection { + + private static WeatherInjection sInstance; + + private final AppDatabase mDatabase; + + private WeatherInjection(final AppDatabase database) { + mDatabase = database; + } + + public static WeatherInjection getInstance(final AppDatabase database) { + if (sInstance == null) { + synchronized (PedInjection.class) { + if (sInstance == null) { + sInstance = new WeatherInjection(database); + } + } + } + return sInstance; + } + + private WeatherDao getWeatherDao() { + return mDatabase.loadWeatherDao(); + } + + public List queryDBWeatherDate(LocalDate date) { + return getWeatherDao().loadAllDateWeatherList(date); + } + + public void deleteDBWeatherDate() { + getWeatherDao().deleteWeatherList(); + } + + public void insertWeatherEntity(WeatherEntity entity){ + getWeatherDao().insertWeatherEntity(entity); + } +} diff --git a/app/src/main/java/com/ic/work/db/dao/PedDao.java b/app/src/main/java/com/ic/work/db/dao/PedDao.java new file mode 100644 index 0000000..7cb31cd --- /dev/null +++ b/app/src/main/java/com/ic/work/db/dao/PedDao.java @@ -0,0 +1,39 @@ +package com.ic.work.db.dao; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; + +import com.ic.work.db.entity.PedEntity; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; + +import java.util.List; + +@Dao +public interface PedDao { + + //查询时间对应的记录,可能为空。 + @Query("SELECT * FROM icPedDb WHERE pedDate = :currDate ") + List loadDatePedList(LocalDate currDate); + + @Query("SELECT COUNT(id) FROM icPedDb") + int queryCountPed(); + + @Query("SELECT * FROM icPedDb ORDER BY datetime(pedDate) limit 1") + List loadOldestDatePedList(); + + @Query("SELECT * FROM icPedDb") + List loadAllDatePedList(); + + @Insert + void insertPedEntity(PedEntity entity); + + //更新记录 + @Query("UPDATE icPedDb SET pedNumber = :number , pedDistance = :distance , pedCalorie = :calorie WHERE id = :id") + void updatePedEntity(int id, int number, float distance, float calorie); + + @Query("DELETE FROM icPedDb WHERE id = :id") + void deletePedEntity(int id); +} diff --git a/app/src/main/java/com/ic/work/db/dao/WeatherDao.java b/app/src/main/java/com/ic/work/db/dao/WeatherDao.java new file mode 100644 index 0000000..7be1051 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/dao/WeatherDao.java @@ -0,0 +1,25 @@ +package com.ic.work.db.dao; + +import androidx.room.Dao; +import androidx.room.Insert; +import androidx.room.Query; + +import com.ic.work.db.entity.WeatherEntity; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; + +import java.util.List; + +@Dao +public interface WeatherDao { + + @Query("SELECT * FROM icWeatherDb WHERE updateTime= :currDate") + List loadAllDateWeatherList(LocalDate currDate); + + @Query("DELETE from icWeatherDb") + void deleteWeatherList(); + + @Insert + void insertWeatherEntity(WeatherEntity entity); +} diff --git a/app/src/main/java/com/ic/work/db/entity/PedEntity.java b/app/src/main/java/com/ic/work/db/entity/PedEntity.java new file mode 100644 index 0000000..9b65131 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/entity/PedEntity.java @@ -0,0 +1,59 @@ +package com.ic.work.db.entity; + +import androidx.room.Entity; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; + +@Entity(tableName = "icPedDb", + indices = {@Index("id")}) +public class PedEntity { + @PrimaryKey(autoGenerate = true) + private int id; + private int pedNumber; + private float pedDistance; + private float pedCalorie; + private LocalDate pedDate; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getPedNumber() { + return pedNumber; + } + + public void setPedNumber(int pedNumber) { + this.pedNumber = pedNumber; + } + + public float getPedDistance() { + return pedDistance; + } + + public void setPedDistance(float pedDistance) { + this.pedDistance = pedDistance; + } + + public float getPedCalorie() { + return pedCalorie; + } + + public void setPedCalorie(float pedCalorie) { + this.pedCalorie = pedCalorie; + } + + public LocalDate getPedDate() { + return pedDate; + } + + public void setPedDate(LocalDate pedDate) { + this.pedDate = pedDate; + } +} diff --git a/app/src/main/java/com/ic/work/db/entity/WeatherEntity.java b/app/src/main/java/com/ic/work/db/entity/WeatherEntity.java new file mode 100644 index 0000000..fbb1993 --- /dev/null +++ b/app/src/main/java/com/ic/work/db/entity/WeatherEntity.java @@ -0,0 +1,94 @@ +package com.ic.work.db.entity; + +import androidx.room.Entity; +import androidx.room.Index; +import androidx.room.PrimaryKey; + +import org.threeten.bp.LocalDate; + +@Entity(tableName = "icWeatherDb", + indices = {@Index("id")}) +public class WeatherEntity { + @PrimaryKey(autoGenerate = true) + private int id; + private String city; + private String statusDay; // 白天状态,如:晴 + private String statusNight; // 晚上状态 + private String figureDay; // 状态索引 + private String figureNight; + private String temperatureDay; // 白天温度 或 最低温度 + private String temperatureNight; // 晚上温度 或 最低温度 + private LocalDate updateTime; // 更新时间 + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStatusDay() { + return statusDay; + } + + public void setStatusDay(String statusDay) { + this.statusDay = statusDay; + } + + public String getStatusNight() { + return statusNight; + } + + public void setStatusNight(String statusNight) { + this.statusNight = statusNight; + } + + public String getFigureDay() { + return figureDay; + } + + public void setFigureDay(String figureDay) { + this.figureDay = figureDay; + } + + public String getFigureNight() { + return figureNight; + } + + public void setFigureNight(String figureNight) { + this.figureNight = figureNight; + } + + public String getTemperatureDay() { + return temperatureDay; + } + + public void setTemperatureDay(String temperatureDay) { + this.temperatureDay = temperatureDay; + } + + public String getTemperatureNight() { + return temperatureNight; + } + + public void setTemperatureNight(String temperatureNight) { + this.temperatureNight = temperatureNight; + } + + public LocalDate getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDate updateTime) { + this.updateTime = updateTime; + } +} diff --git a/app/src/main/java/com/ic/work/event/BloodCheckResultEvent.java b/app/src/main/java/com/ic/work/event/BloodCheckResultEvent.java new file mode 100644 index 0000000..e4cee9e --- /dev/null +++ b/app/src/main/java/com/ic/work/event/BloodCheckResultEvent.java @@ -0,0 +1,27 @@ +package com.ic.work.event; + +public class BloodCheckResultEvent { + private int high; + private int low; + private int heart; + + + public BloodCheckResultEvent(int high, int low, int heart) { + this.high = high; + this.low = low; + this.heart = heart; + } + + public int getHigh() { + return high; + } + + public int getLow() { + return low; + } + + public int getHeart() { + return heart; + } + +} diff --git a/app/src/main/java/com/ic/work/event/BloodCheckTipsEvent.java b/app/src/main/java/com/ic/work/event/BloodCheckTipsEvent.java new file mode 100644 index 0000000..850f103 --- /dev/null +++ b/app/src/main/java/com/ic/work/event/BloodCheckTipsEvent.java @@ -0,0 +1,27 @@ +package com.ic.work.event; + +public class BloodCheckTipsEvent { + private int topTips; + private int bottomTips; + + public BloodCheckTipsEvent(int topTips, int bottomTips) { + this.topTips = topTips; + this.bottomTips = bottomTips; + } + + public int getTopTips() { + return topTips; + } + + public void setTopTips(int topTips) { + this.topTips = topTips; + } + + public int getBottomTips() { + return bottomTips; + } + + public void setBottomTips(int bottomTips) { + this.bottomTips = bottomTips; + } +} diff --git a/app/src/main/java/com/ic/work/event/LocationResultEvent.java b/app/src/main/java/com/ic/work/event/LocationResultEvent.java new file mode 100644 index 0000000..9b61e33 --- /dev/null +++ b/app/src/main/java/com/ic/work/event/LocationResultEvent.java @@ -0,0 +1,14 @@ +package com.ic.work.event; + +public class LocationResultEvent { + + private String mCity; + + public LocationResultEvent(String city) { + this.mCity = city; + } + + public String getmCity() { + return mCity; + } +} diff --git a/app/src/main/java/com/ic/work/event/PedCountEvent.java b/app/src/main/java/com/ic/work/event/PedCountEvent.java new file mode 100644 index 0000000..bae08de --- /dev/null +++ b/app/src/main/java/com/ic/work/event/PedCountEvent.java @@ -0,0 +1,13 @@ +package com.ic.work.event; + +public class PedCountEvent { + private int pedCount; + + public PedCountEvent(int count) { + this.pedCount = count; + } + + public int getPedCount() { + return pedCount; + } +} diff --git a/app/src/main/java/com/ic/work/event/PedRecordResultEvent.java b/app/src/main/java/com/ic/work/event/PedRecordResultEvent.java new file mode 100644 index 0000000..14699d8 --- /dev/null +++ b/app/src/main/java/com/ic/work/event/PedRecordResultEvent.java @@ -0,0 +1,17 @@ +package com.ic.work.event; + +import com.ic.aidl.ped.RecordParcelable; + +import java.util.List; + +public class PedRecordResultEvent { + private List recordList; + + public List getRecordList() { + return recordList; + } + + public PedRecordResultEvent(List recordList) { + this.recordList = recordList; + } +} diff --git a/app/src/main/java/com/ic/work/event/PedSettingEvent.java b/app/src/main/java/com/ic/work/event/PedSettingEvent.java new file mode 100644 index 0000000..11b0891 --- /dev/null +++ b/app/src/main/java/com/ic/work/event/PedSettingEvent.java @@ -0,0 +1,19 @@ +package com.ic.work.event; + +public class PedSettingEvent { + private int type; + private int value; + + public PedSettingEvent(int type, int value) { + this.type = type; + this.value = value; + } + + public int getType() { + return type; + } + + public int getValue() { + return value; + } +} diff --git a/app/src/main/java/com/ic/work/event/WeatherAgainEvent.java b/app/src/main/java/com/ic/work/event/WeatherAgainEvent.java new file mode 100644 index 0000000..0fc0cb5 --- /dev/null +++ b/app/src/main/java/com/ic/work/event/WeatherAgainEvent.java @@ -0,0 +1,4 @@ +package com.ic.work.event; + +public class WeatherAgainEvent { +} diff --git a/app/src/main/java/com/ic/work/event/WeatherResultEvent.java b/app/src/main/java/com/ic/work/event/WeatherResultEvent.java new file mode 100644 index 0000000..b00277d --- /dev/null +++ b/app/src/main/java/com/ic/work/event/WeatherResultEvent.java @@ -0,0 +1,15 @@ +package com.ic.work.event; + +import com.ic.aidl.weather.WeatherParcelable; + +public class WeatherResultEvent { + private WeatherParcelable parcelable; + + public WeatherResultEvent(WeatherParcelable parcelable) { + this.parcelable = parcelable; + } + + public WeatherParcelable getParcelable() { + return parcelable; + } +} diff --git a/app/src/main/java/com/ic/work/hardware/BloodRunnable.java b/app/src/main/java/com/ic/work/hardware/BloodRunnable.java new file mode 100644 index 0000000..3486560 --- /dev/null +++ b/app/src/main/java/com/ic/work/hardware/BloodRunnable.java @@ -0,0 +1,82 @@ +package com.ic.work.hardware; + +import com.ic.work.event.BloodCheckResultEvent; +import com.ic.work.event.BloodCheckTipsEvent; +import com.ic.work.utils.HardwareUtils; +import com.ic.work.utils.IcLog; + +import org.greenrobot.eventbus.EventBus; + +import static com.ic.aidl.blood.BloodState.BLOOD_ING_CHECK; +import static com.ic.aidl.blood.BloodState.BLOOD_NOT_DATA_CHECK; +import static com.ic.aidl.blood.BloodState.BLOOD_NOT_DEVICE; +import static com.ic.aidl.blood.BloodState.BLOOD_NOT_WEAR; +import static com.ic.aidl.blood.BloodState.BLOOD_NULL_TIPS; +import static com.ic.aidl.blood.BloodState.BLOOD_PLEASE_QUIET; +import static com.ic.aidl.blood.BloodState.BLOOD_START_CHECK; +import static com.ic.aidl.blood.BloodState.BLOOD_STOP_CHECK; + +public class BloodRunnable implements Runnable{ + + private static final String TAG="BloodRunnable"; + + @Override + public void run() { + int ndkHeart = 0; + int ndkHigh = 0; + int ndkLow = 0; + int count = 0; + + if (HardwareUtils.isPPGavailable()) { + sendTipsEventBus(BLOOD_NULL_TIPS,BLOOD_NOT_DEVICE); + return; + } + + //开启 + HardwareUtils.onNdkEnablePPG(); + + sendTipsEventBus(BLOOD_PLEASE_QUIET,BLOOD_START_CHECK); + + try { + while (!Thread.currentThread().isInterrupted()) { + ndkHeart = HardwareUtils.getNdkPPGValue(); + if (HardwareUtils.isWeared()) { + //未佩戴 + sendTipsEventBus(BLOOD_NULL_TIPS,BLOOD_NOT_WEAR); + if (count > 15) break; + count++; + } else { + if (ndkHeart > 0) { + //佩戴好,并且已经或到心率的值,则获取低压和高压的值 + ndkHigh = HardwareUtils.getNdkHighBloodValue(); + ndkLow = HardwareUtils.getNdkLowBloodValue(); + //跳出循环,不在获取 + break; + } else { + //正在测量中,请稍等 + sendTipsEventBus(BLOOD_PLEASE_QUIET,BLOOD_ING_CHECK); + } + } + + Thread.sleep(1000); + } + + if (count > 15 || ndkHeart == 0) { + sendTipsEventBus(BLOOD_STOP_CHECK, BLOOD_NOT_DATA_CHECK); + } else { + EventBus.getDefault().post(new BloodCheckResultEvent(ndkHigh,ndkLow,ndkHeart)); + } + + HardwareUtils.onNdkDisablePPG(); + + } catch (InterruptedException e) { + IcLog.e(TAG, "Stop Get Heart Value"); + }finally { + HardwareUtils.onNdkDisablePPG(); + } + } + + private void sendTipsEventBus(int top,int bottom){ + EventBus.getDefault().post(new BloodCheckTipsEvent(top, bottom)); + } +} diff --git a/app/src/main/java/com/ic/work/hardware/PedRecordRunnable.java b/app/src/main/java/com/ic/work/hardware/PedRecordRunnable.java new file mode 100644 index 0000000..35eae9d --- /dev/null +++ b/app/src/main/java/com/ic/work/hardware/PedRecordRunnable.java @@ -0,0 +1,40 @@ +package com.ic.work.hardware; + +import com.ic.aidl.ped.RecordParcelable; +import com.ic.work.db.PedInjection; +import com.ic.work.db.entity.PedEntity; +import com.ic.work.event.PedRecordResultEvent; + +import org.greenrobot.eventbus.EventBus; +import org.threeten.bp.format.DateTimeFormatter; + +import java.util.ArrayList; +import java.util.List; + +public class PedRecordRunnable implements Runnable { + private PedInjection mPedDb; + + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + + public PedRecordRunnable(PedInjection pedDB) { + mPedDb = pedDB; + } + + @Override + public void run() { + List query = mPedDb.queryDBPedAllList(); + List recordList = new ArrayList<>(); + for (int i=0; i< query.size(); i++){ + RecordParcelable recordP = new RecordParcelable(); + recordP.setNumber(query.get(i).getPedNumber()); + recordP.setCalorie(String.valueOf(query.get(i).getPedCalorie())); + recordP.setDistance(String.valueOf(query.get(i).getPedDistance())); + recordP.setDate(query.get(i).getPedDate().format(formatter)); + + recordList.add(recordP); + } + + //发送数据到主线程 + EventBus.getDefault().post(new PedRecordResultEvent(recordList)); + } +} diff --git a/app/src/main/java/com/ic/work/hardware/PedRunnable.java b/app/src/main/java/com/ic/work/hardware/PedRunnable.java new file mode 100644 index 0000000..d127058 --- /dev/null +++ b/app/src/main/java/com/ic/work/hardware/PedRunnable.java @@ -0,0 +1,123 @@ +package com.ic.work.hardware; + +import com.ic.work.db.PedInjection; +import com.ic.work.db.entity.PedEntity; +import com.ic.work.event.PedCountEvent; +import com.ic.work.utils.HardwareUtils; +import com.ic.work.utils.IcLog; +import com.ic.work.utils.PedUtil; + +import org.greenrobot.eventbus.EventBus; +import org.threeten.bp.LocalDate; + +import java.math.BigDecimal; +import java.util.List; + +public class PedRunnable implements Runnable { + + private static final String TAG = "PedRunnable"; + + private PedInjection mPedDb; + + private int mHeight; + private int mWeight; + + public PedRunnable(PedInjection pedDB, int height, int weight) { + mPedDb = pedDB; + mHeight = height; + mWeight = weight; + } + + public void setHeight(int mHeight) { + this.mHeight = mHeight; + } + + public void setWeight(int mWeight) { + this.mWeight = mWeight; + } + + @Override + public void run() { + //1.先获取一次当前的计步数 + int currCount = HardwareUtils.getNdkStepCountValue(); + IcLog.i(TAG, "Ped Count" + currCount); + + int size = mPedDb.queryDBPedCount(); + if (size == 0) { + //如果数据库中无记录,把当前数据插入到数据库中 + insertDBPedEntity(currCount, LocalDate.now(),size); + } else { + //2.去查询数据中是否有当天的记录。 + List todayPed = mPedDb.queryDBPedDate(LocalDate.now()); + if (todayPed != null && todayPed.size() > 0) { + //3.如果数据中有当天的数据,并更新数据 + if (currCount > 0 && currCount > todayPed.get(0).getPedNumber()) { + todayPed.get(0).setPedNumber(currCount); + updateDBPedEntity(todayPed.get(0)); + } + } else { + //4.如果数据库中没有当天的数据,则把当前的数据更新前一天的数据中 + // 并且重置计步,并在数据库中新建一条数据 + //重置计步 + HardwareUtils.resetNdkStepCountValue(); + //获取前一天的数据 + List beforePed = mPedDb.queryDBPedDate(LocalDate.now().minusDays(1)); + if (beforePed != null && beforePed.size() > 0) { + beforePed.get(0).setPedNumber(currCount); + updateDBPedEntity(beforePed.get(0)); + + insertDBPedEntity(0, LocalDate.now(),size); + //发送给主线程。主线更新数据UI + EventBus.getDefault().post(new PedCountEvent(0)); + return; + } else { + //如果没有前一天没有数据。则直接 插入今天的数据 + insertDBPedEntity(currCount, LocalDate.now(),size); + } + } + } + + //发送给主线程。主线更新数据UI + EventBus.getDefault().post(new PedCountEvent(currCount)); + } + + private PedEntity createEntity(int number, LocalDate date) { + + PedEntity entity = new PedEntity(); + entity.setPedNumber(number); + entity.setPedDistance(getDistanceValue(number)); + entity.setPedCalorie(getCalorieValue(number)); + entity.setPedDate(date); + + return entity; + } + + private void insertDBPedEntity(int number, LocalDate date,int size) { + //判断 size 超过 + if(size >= 60){ + //删除一条最早的数据 + List entities = mPedDb.queryDBPedOldestList(); + if(entities != null && entities.size() == 1){ + mPedDb.deletePedEntity(entities.get(0).getId()); + } + } + mPedDb.insertDBPedDate(createEntity(number, date)); + } + + private void updateDBPedEntity(PedEntity entity) { + int number = entity.getPedNumber(); + entity.setPedDistance(getDistanceValue(number)); + entity.setPedCalorie(getCalorieValue(number)); + mPedDb.updateDBPedDate(entity); + } + + private float getCalorieValue(int number) { + BigDecimal bg = new BigDecimal(PedUtil.calcConsumeEnergy(mHeight, mWeight, number)); + return bg.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); + } + + private float getDistanceValue(int number) { + BigDecimal bg = new BigDecimal(PedUtil.calcDistanceBySteps(mHeight, number)); + return bg.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue(); + } +} diff --git a/app/src/main/java/com/ic/work/process/BloodProcess.java b/app/src/main/java/com/ic/work/process/BloodProcess.java new file mode 100644 index 0000000..af88312 --- /dev/null +++ b/app/src/main/java/com/ic/work/process/BloodProcess.java @@ -0,0 +1,98 @@ +package com.ic.work.process; + +import android.os.IBinder; +import android.os.RemoteCallbackList; +import android.os.RemoteException; + +import com.ic.aidl.blood.IBloodAidlInterface; +import com.ic.aidl.blood.IBloodRemoteService; +import com.ic.work.ThreadPoolManager; +import com.ic.work.hardware.BloodRunnable; +import com.ic.work.utils.IcLog; + + +public class BloodProcess { + private static final String TAG = "BloodProcess"; + + private RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); + + private BloodRunnable mBloodRun; + + public BloodProcess() { + mBloodRun = new BloodRunnable(); + } + + public IBinder getBloodBinder() { + return bloodBinder; + } + + private IBloodRemoteService.Stub bloodBinder = new IBloodRemoteService.Stub() { + @Override + public void registerCallback(IBloodAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.register(cb); + } + } + + @Override + public void unregisterCallback(IBloodAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.unregister(cb); + } + } + + @Override + public void startCheckBlood() throws RemoteException { + ThreadPoolManager.getInstance().execute(mBloodRun); + } + + @Override + public void stopCheckBlood() throws RemoteException { + ThreadPoolManager.getInstance().remove(mBloodRun); + } + }; + + public void sendBloodCheckResult(int heih, int low, int heart) { + int N = 0; + try { + N = mCallbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + mCallbacks.getBroadcastItem(i).updateBloodCheckResult(heih, low, heart); + } + } catch (NullPointerException e) { + IcLog.e(TAG, e.getMessage()); + } catch (RemoteException er) { + IcLog.e(TAG, er.getMessage()); + } finally { + try { + if (N > 0) { + mCallbacks.finishBroadcast(); + } + } catch (IllegalArgumentException ll) { + IcLog.e(TAG, ll.getMessage()); + } + } + } + + public void sendBloodCheckTips(int top, int bottom) { + int N = 0; + try { + N = mCallbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + mCallbacks.getBroadcastItem(i).updateBloodCheckTips(top, bottom); + } + } catch (NullPointerException e) { + IcLog.e(TAG, e.getMessage()); + } catch (RemoteException er) { + IcLog.e(TAG, er.getMessage()); + } finally { + try { + if (N > 0) { + mCallbacks.finishBroadcast(); + } + } catch (IllegalArgumentException ll) { + IcLog.e(TAG, ll.getMessage()); + } + } + } +} diff --git a/app/src/main/java/com/ic/work/process/PedProcess.java b/app/src/main/java/com/ic/work/process/PedProcess.java new file mode 100644 index 0000000..6c3f817 --- /dev/null +++ b/app/src/main/java/com/ic/work/process/PedProcess.java @@ -0,0 +1,126 @@ +package com.ic.work.process; + +import android.os.Binder; +import android.os.IBinder; +import android.os.RemoteCallbackList; +import android.os.RemoteException; + +import com.ic.aidl.ped.IPedAidlInterface; +import com.ic.aidl.ped.IPedRemoteService; +import com.ic.aidl.ped.RecordParcelable; +import com.ic.work.ThreadPoolManager; +import com.ic.work.WorkServiceApp; +import com.ic.work.event.PedSettingEvent; +import com.ic.work.hardware.PedRecordRunnable; +import com.ic.work.hardware.PedRunnable; +import com.ic.work.utils.IcLog; + +import org.greenrobot.eventbus.EventBus; + +import java.util.List; + +public class PedProcess { + private static final String TAG = "PedProcess"; + + private RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); + + private PedRunnable mPedRun; + private PedRecordRunnable mRecordRun; + + public PedProcess(WorkServiceApp app, int height, int weight) { + mPedRun = new PedRunnable(app.getRepository(), height, weight); + mRecordRun = new PedRecordRunnable(app.getRepository()); + } + + public IBinder getPedBinder() { + return pedBinder; + } + + private IPedRemoteService.Stub pedBinder = new IPedRemoteService.Stub() { + @Override + public void registerCallback(IPedAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.register(cb); + } + } + + @Override + public void unregisterCallback(IPedAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.unregister(cb); + } + } + + @Override + public void queryPedCount() throws RemoteException { + ThreadPoolManager.getInstance().execute(mPedRun); + } + + @Override + public void queryPedRecord() throws RemoteException { + ThreadPoolManager.getInstance().execute(mRecordRun); + } + + @Override + public void syncPedHeightSetting(int height) throws RemoteException { + EventBus.getDefault().post(new PedSettingEvent(1, height)); + } + + @Override + public void syncPedWeightSetting(int weight) throws RemoteException { + EventBus.getDefault().post(new PedSettingEvent(2, weight)); + } + }; + + public void updateHeight(int height){ + mPedRun.setHeight(height); + } + + public void updateWeight(int weight){ + mPedRun.setWeight(weight); + } + + public void sendPedCount(int count) { + int N = 0; + try { + N = mCallbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + mCallbacks.getBroadcastItem(i).updatePedCount(count); + } + } catch (NullPointerException e) { + IcLog.e(TAG, e.getMessage()); + } catch (RemoteException er) { + IcLog.e(TAG, er.getMessage()); + } finally { + try { + if (N > 0) { + mCallbacks.finishBroadcast(); + } + } catch (IllegalArgumentException ll) { + IcLog.e(TAG, ll.getMessage()); + } + } + } + + public void sendPedRecord(List record) { + int N = 0; + try { + N = mCallbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + mCallbacks.getBroadcastItem(i).updatePedRecord(record); + } + } catch (NullPointerException e) { + IcLog.e(TAG, e.getMessage()); + } catch (RemoteException er) { + IcLog.e(TAG, er.getMessage()); + } finally { + try { + if (N > 0) { + mCallbacks.finishBroadcast(); + } + } catch (IllegalArgumentException ll) { + IcLog.e(TAG, ll.getMessage()); + } + } + } +} diff --git a/app/src/main/java/com/ic/work/process/WeatherProcess.java b/app/src/main/java/com/ic/work/process/WeatherProcess.java new file mode 100644 index 0000000..77058ff --- /dev/null +++ b/app/src/main/java/com/ic/work/process/WeatherProcess.java @@ -0,0 +1,73 @@ +package com.ic.work.process; + +import android.os.IBinder; +import android.os.RemoteCallbackList; +import android.os.RemoteException; + +import com.ic.aidl.weather.IWeatherAidlInterface; +import com.ic.aidl.weather.IWeatherRemoteService; +import com.ic.aidl.weather.WeatherParcelable; +import com.ic.work.ThreadPoolManager; +import com.ic.work.WorkServiceApp; +import com.ic.work.utils.IcLog; +import com.ic.work.weather.WeatherDBRun; + +public class WeatherProcess { + + private static final String TAG = "WeatherProcess"; + + private RemoteCallbackList mCallbacks = new RemoteCallbackList<>(); + + private WeatherDBRun weatherRun; + + public WeatherProcess(WorkServiceApp app) { + weatherRun = new WeatherDBRun(app.getWeatherRepository()); + } + + public IBinder getWeatherBinder(){ + return weatherBinder; + } + + private IWeatherRemoteService.Stub weatherBinder = new IWeatherRemoteService.Stub() { + @Override + public void registerCallback(IWeatherAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.register(cb); + } + } + + @Override + public void unregisterCallback(IWeatherAidlInterface cb) throws RemoteException { + if (cb != null) { + mCallbacks.unregister(cb); + } + } + + @Override + public void queryWeatherInfo() throws RemoteException { + ThreadPoolManager.getInstance().execute(weatherRun); + } + }; + + public void sendCurrWeather(WeatherParcelable parcelable) { + int N = 0; + try { + N = mCallbacks.beginBroadcast(); + for (int i = 0; i < N; i++) { + mCallbacks.getBroadcastItem(i).updateCurrWeather(parcelable); + } + } catch (NullPointerException e) { + IcLog.e(TAG, e.getMessage()); + } catch (RemoteException er) { + IcLog.e(TAG, er.getMessage()); + } finally { + try { + if (N > 0) { + mCallbacks.finishBroadcast(); + } + } catch (IllegalArgumentException ll) { + IcLog.e(TAG, ll.getMessage()); + } + } + } +} diff --git a/app/src/main/java/com/ic/work/utils/AppExecutors.java b/app/src/main/java/com/ic/work/utils/AppExecutors.java new file mode 100644 index 0000000..a1f57fc --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/AppExecutors.java @@ -0,0 +1,50 @@ +package com.ic.work.utils; + +import android.os.Handler; +import android.os.Looper; + +import androidx.annotation.NonNull; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +public class AppExecutors { + + private final Executor mDiskIO; + + private final Executor mNetworkIO; + + private final Executor mMainThread; + + private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) { + this.mDiskIO = diskIO; + this.mNetworkIO = networkIO; + this.mMainThread = mainThread; + } + + public AppExecutors() { + this(Executors.newSingleThreadExecutor(), Executors.newFixedThreadPool(3), + new MainThreadExecutor()); + } + + public Executor diskIO() { + return mDiskIO; + } + + public Executor networkIO() { + return mNetworkIO; + } + + public Executor mainThread() { + return mMainThread; + } + + private static class MainThreadExecutor implements Executor { + private Handler mainThreadHandler = new Handler(Looper.getMainLooper()); + + @Override + public void execute(@NonNull Runnable command) { + mainThreadHandler.post(command); + } + } +} diff --git a/app/src/main/java/com/ic/work/utils/HardwareUtils.java b/app/src/main/java/com/ic/work/utils/HardwareUtils.java new file mode 100644 index 0000000..13e029a --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/HardwareUtils.java @@ -0,0 +1,87 @@ +package com.ic.work.utils; + +import com.ic.jni.ICJniUtils; + +public class HardwareUtils { + + private static final String TAG = "HardwareUtils"; + + public static boolean isPPGavailable() { + try { + return ICJniUtils.isPPGavailable() == 0; + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return true; + } + } + + public static void onNdkEnablePPG() { + try { + ICJniUtils.enablePPG(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + + public static void onNdkDisablePPG() { + try { + ICJniUtils.disablePPG(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + } + } + + public static boolean isWeared() { + try { + return ICJniUtils.isWeared() == 0; + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return true; + } + } + + public static int getNdkPPGValue() { + try { + return ICJniUtils.getPPG(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return 0; + } + } + + public static int getNdkHighBloodValue() { + try { + return ICJniUtils.getHighBloodPressure(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return 0; + } + } + + public static int getNdkLowBloodValue() { + try { + return ICJniUtils.getLowBloodPressure(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return 0; + } + } + + public static int getNdkStepCountValue() { + try { + return ICJniUtils.getStepCount(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return 0; + } + } + + public static int resetNdkStepCountValue() { + try { + return ICJniUtils.resetStepCount(); + } catch (Exception e) { + IcLog.e(TAG, e.getMessage()); + return 0; + } + } +} diff --git a/app/src/main/java/com/ic/work/utils/IcLog.java b/app/src/main/java/com/ic/work/utils/IcLog.java new file mode 100644 index 0000000..a7bb72c --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/IcLog.java @@ -0,0 +1,59 @@ +package com.ic.work.utils; + +import android.util.Log; + +import com.ic.work.BuildConfig; + +/** + * @author RyanLee + * @date 2018/2/2 + */ + +public class IcLog { + + private static final String DOT = "."; + private static boolean isDebug = BuildConfig.DEBUG; + private static String tagHead = ""; + + public static void v(String tag, String msg) { + if (isDebug) { + Log.v(mergeHeadTag(tag), msg); + } + } + + public static void d(String tag, String msg) { + if (isDebug) { + Log.d(mergeHeadTag(tag), msg); + } + } + + public static void i(String tag, String msg) { + if (isDebug) { + Log.i(mergeHeadTag(tag), msg); + } + } + + public static void w(String tag, String msg) { + if (isDebug) { + Log.w(mergeHeadTag(tag), msg); + } + } + + public static void e(String tag, String msg) { + if (isDebug) { + Log.e(mergeHeadTag(tag), msg); + } + } + + public static void setDebug(boolean debug) { + isDebug = debug; + } + + public static void setLogHead(String head) { + tagHead = head + DOT; + } + + private static String mergeHeadTag(final String tag) { + return tagHead + tag; + } +} diff --git a/app/src/main/java/com/ic/work/utils/PedUtil.java b/app/src/main/java/com/ic/work/utils/PedUtil.java new file mode 100644 index 0000000..e4d87ae --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/PedUtil.java @@ -0,0 +1,53 @@ +package com.ic.work.utils; + +public class PedUtil { + + private static final float LB_KG_CONVERSION_RATE = 0.45359237f; + private static final float KM_TO_MILE_CONVERSION_RATE = 0.62147119f; + private static final float INCH_CM_CONVERSION_RATE = 2.54f; + private static final int FOOT_INCH_CONVERSION_RATE = 12; + + //根据身高、步数计算路程 + public static float calcDistanceBySteps(int height, int steps) { + float var = 0f; + if (height < 154) { + var = (float) 16 / 42; + } else if (height > 174) { + var = (float) 17 / 42; + } else { + var = (float) 11 / 28; + } + + return (steps * height * var + height / 7) / 100000; // km + } + + public static float calcConsumeEnergy(int height, int weight, int steps) { + float consumeEnergy = 0f; + if (steps > 0) { + consumeEnergy = (0.53f * height + 0.58f * weight + 0.04f * steps) - 135; + consumeEnergy = (int) (consumeEnergy * 10) / 10f; + consumeEnergy = Math.max(consumeEnergy, 0.1f); + } + return consumeEnergy; + } + + //单位转换 Inch 英寸 -> cm + public static float inchToCm(float inch) { + return (inch * INCH_CM_CONVERSION_RATE); + } + + //单位转换 km -> mile 英里 + public static float kmToMile(float km) { + return (km * KM_TO_MILE_CONVERSION_RATE); + } + + //单位转换 kg -> lb 磅 + public static float kgTolb(float kg) { + return (kg / LB_KG_CONVERSION_RATE); + } + + //单位转换 lb 磅 -> kg + public static float lbTokg(float lb) { + return (lb * LB_KG_CONVERSION_RATE); + } +} diff --git a/app/src/main/java/com/ic/work/utils/SPUtils.java b/app/src/main/java/com/ic/work/utils/SPUtils.java new file mode 100644 index 0000000..2cc5ccb --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/SPUtils.java @@ -0,0 +1,38 @@ +package com.ic.work.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +public class SPUtils { + + private static final String Ped_Height = "Ped_Height"; + private static final String Ped_Weight = "Ped_Weight"; + + public static SharedPreferences getSP(Context context) { + return context.getSharedPreferences("IcPedSet", Context.MODE_PRIVATE); + } + + public static int getPedHeightSP(Context context) { + return getSP(context).getInt(Ped_Height, 170); + } + + public static int getPedWighttSP(Context context) { + return getSP(context).getInt(Ped_Weight, 75); + } + + public static void setPedHeightSP(Context context,int height) { + SharedPreferences.Editor editor = getSP(context).edit(); + if (editor != null) { + editor.putInt(Ped_Weight, height); + editor.apply(); + } + } + + public static void setPedWighttSP(Context context,int weight) { + SharedPreferences.Editor editor = getSP(context).edit(); + if (editor != null) { + editor.putInt(Ped_Weight, weight); + editor.apply(); + } + } +} diff --git a/app/src/main/java/com/ic/work/utils/ServiceUtil.java b/app/src/main/java/com/ic/work/utils/ServiceUtil.java new file mode 100644 index 0000000..a0942ba --- /dev/null +++ b/app/src/main/java/com/ic/work/utils/ServiceUtil.java @@ -0,0 +1,42 @@ +package com.ic.work.utils; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; + +import java.util.List; + +public class ServiceUtil { + + public static void startServiceUtil(Context context , String serviceAction, String packageName) { + Intent intent = getExplicitIntent(context, new Intent(serviceAction)); + if(intent != null){ + intent.setPackage(packageName); + context.startService(intent); + } + } + + public static void bindServiceUtil(Context context , String action, ServiceConnection connection,int type) { + Intent in = getExplicitIntent(context, new Intent(action)); + if(in != null){ + in.putExtra("REQ_TYPE",type); + context.bindService(in, connection, 0); + } + } + + private static Intent getExplicitIntent(Context context, Intent impl) { + List resolveInfo = context.getPackageManager().queryIntentServices(impl, 0); + + if (resolveInfo.size() != 1) return null; + + Intent intent = new Intent(impl); + ServiceInfo info = resolveInfo.get(0).serviceInfo; + if (info == null) return null; + intent.setComponent(new ComponentName(info.packageName, info.name)); + + return intent; + } +} diff --git a/app/src/main/java/com/ic/work/weather/LocationHelper.java b/app/src/main/java/com/ic/work/weather/LocationHelper.java new file mode 100644 index 0000000..250369c --- /dev/null +++ b/app/src/main/java/com/ic/work/weather/LocationHelper.java @@ -0,0 +1,85 @@ +package com.ic.work.weather; + +import android.content.Context; + +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationClientOption; +import com.amap.api.location.AMapLocationListener; +import com.ic.work.event.LocationResultEvent; +import com.ic.work.utils.IcLog; + +import org.greenrobot.eventbus.EventBus; + +public class LocationHelper { + + private static final String TAG ="LocationHelper"; + + public AMapLocationClient mLocationClient; + + public LocationHelper(Context context) { + mLocationClient = new AMapLocationClient(context); + //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。 + AMapLocationListener mLocationListener = aMapLocation -> { + if (aMapLocation != null) { + if (aMapLocation.getErrorCode() == 0) { + IcLog.i(TAG,"Loaction City:"+aMapLocation.getCity()); + EventBus.getDefault().post(new LocationResultEvent(aMapLocation.getCity())); + } else { + //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。 + IcLog.e(TAG, "location Error, ErrCode:" + + aMapLocation.getErrorCode() + ", errInfo:" + + aMapLocation.getErrorInfo()); + EventBus.getDefault().post(new LocationResultEvent("")); + } + } + }; + mLocationClient.setLocationListener(mLocationListener); + mLocationClient.setLocationOption(getDefaultOption()); + } + + public void startLocationService(){ + if(mLocationClient != null){ + mLocationClient.startLocation(); + } + } + + public void stopLocationService(){ + if(mLocationClient != null){ + mLocationClient.stopLocation(); + mLocationClient.onDestroy(); + + mLocationClient = null; + } + } + + private AMapLocationClientOption getDefaultOption() { + AMapLocationClientOption mOption = new AMapLocationClientOption(); + + // 高德地图默认值 + mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式 + mOption.setGpsFirst(false);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭 + mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效 + mOption.setInterval(2000);//可选,设置定位间隔。默认为2秒 + mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true + mOption.setOnceLocation(false);//可选,设置是否单次定位。默认是false + mOption.setOnceLocationLatest(false);//可选,设置是否等待wifi刷新,默认为false.如果设置为true,会自动变为单次定位,持续定位时不要使用 + AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选, 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP + mOption.setSensorEnable(false);//可选,设置是否使用传感器。默认是false + mOption.setWifiScan(true); //可选,设置是否开启wifi扫描。默认为true,如果设置为false会同时停止主动刷新,停止以后完全依赖于系统刷新,定位位置可能存在误差 + mOption.setLocationCacheEnable(true); //可选,设置是否使用缓存定位,默认为true + + + // 自定义 + mOption.setHttpTimeOut(10000); + mOption.setInterval(10000); + + // 一次定位设置 + // 该方法默认为false。 + mOption.setOnceLocation(true); + // 关闭缓存机制 + mOption.setLocationCacheEnable(false); + + return mOption; + } + +} diff --git a/app/src/main/java/com/ic/work/weather/WeatherDBRun.java b/app/src/main/java/com/ic/work/weather/WeatherDBRun.java new file mode 100644 index 0000000..3e882b9 --- /dev/null +++ b/app/src/main/java/com/ic/work/weather/WeatherDBRun.java @@ -0,0 +1,52 @@ +package com.ic.work.weather; + +import com.ic.aidl.weather.WeatherParcelable; +import com.ic.work.db.WeatherInjection; +import com.ic.work.db.entity.WeatherEntity; +import com.ic.work.event.WeatherAgainEvent; +import com.ic.work.event.WeatherResultEvent; + +import org.greenrobot.eventbus.EventBus; +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; + +import java.util.List; + +public class WeatherDBRun implements Runnable { + + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + + private WeatherInjection weatherDb; + + public WeatherDBRun(WeatherInjection weather){ + this.weatherDb = weather; + } + + @Override + public void run() { + + List weatherList = weatherDb.queryDBWeatherDate(LocalDate.now()); + if(weatherList == null || weatherList.size() ==0){ + //通知主线程 开始定位 并通过Socket 获取天气 + EventBus.getDefault().post(new WeatherAgainEvent()); + //删除表中所有数据 + weatherDb.deleteDBWeatherDate(); + }else { + WeatherEntity entity = weatherList.get(0); + + WeatherParcelable parcelable = new WeatherParcelable(); + parcelable.setCity(entity.getCity()); + parcelable.setFigureDay(entity.getFigureDay()); + parcelable.setFigureNight(entity.getFigureNight()); + parcelable.setStatusDay(entity.getStatusDay()); + parcelable.setStatusNight(entity.getStatusNight()); + parcelable.setTemperatureDay(entity.getTemperatureDay()); + parcelable.setTemperatureNight(entity.getTemperatureNight()); + parcelable.setUpdateTime(entity.getUpdateTime().format(formatter)); + + //通知主线程 更新UI + EventBus.getDefault().post(new WeatherResultEvent(parcelable)); + } + } +} diff --git a/app/src/main/java/com/ic/work/weather/WeatherHelper.java b/app/src/main/java/com/ic/work/weather/WeatherHelper.java new file mode 100644 index 0000000..41d33e9 --- /dev/null +++ b/app/src/main/java/com/ic/work/weather/WeatherHelper.java @@ -0,0 +1,47 @@ +package com.ic.work.weather; + +import android.content.Context; +import android.text.TextUtils; + +import com.alibaba.fastjson.JSONObject; +import com.ic.work.ThreadPoolManager; +import com.ic.work.db.WeatherInjection; +import com.ic.work.weather.melon.SocketThread; + +public class WeatherHelper { + + private LocationHelper mLocation = null; + + public void startLocation(Context context) { + mLocation = new LocationHelper(context); + mLocation.startLocationService(); + } + + private void stopLocation() { + if (mLocation != null) { + mLocation.stopLocationService(); + mLocation = null; + } + } + + + public void queryWeatherServerInfo(WeatherInjection weatherDb,String city) { + + stopLocation(); + + if(TextUtils.isEmpty(city)){ + return; + } + + final String serverHost = "118.190.120.79"; + final int port = 11645; + + JSONObject paramJson = new JSONObject(); + paramJson.put("cmd", "getserviceip"); + paramJson.put("channel", "西瓜皮-西瓜皮"); + final String param = paramJson.toJSONString(); + + SocketThread socket = new SocketThread(weatherDb,serverHost, port, param,city); + ThreadPoolManager.getInstance().execute(socket); + } +} diff --git a/app/src/main/java/com/ic/work/weather/melon/SocketThread.java b/app/src/main/java/com/ic/work/weather/melon/SocketThread.java new file mode 100644 index 0000000..f770dc7 --- /dev/null +++ b/app/src/main/java/com/ic/work/weather/melon/SocketThread.java @@ -0,0 +1,173 @@ +package com.ic.work.weather.melon; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ic.aidl.weather.WeatherParcelable; +import com.ic.work.BuildConfig; +import com.ic.work.db.WeatherInjection; +import com.ic.work.db.entity.WeatherEntity; +import com.ic.work.event.WeatherResultEvent; +import com.ic.work.utils.IcLog; + +import org.greenrobot.eventbus.EventBus; +import org.threeten.bp.LocalDate; +import org.threeten.bp.OffsetDateTime; +import org.threeten.bp.format.DateTimeFormatter; + +import static java.nio.charset.StandardCharsets.UTF_8; + +public class SocketThread implements Runnable { + private static final String TAG = "SocketThread"; + + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + + private String mIp; + private int mPort; + private String param; + + private String mCity; + + private SocketUtils mSocketUtils; + + private WeatherInjection weatherInjection; + + public SocketThread(WeatherInjection weatherDb, String ip, int port, String param, String city) { + mSocketUtils = new SocketUtils(); + + weatherInjection = weatherDb; + + this.mIp = ip; + this.mPort = port; + this.param = param; + this.mCity = city; + } + + @Override + public void run() { + + byte[] response = null; + int count = 0; + boolean isQueryWeather = false; + + while (true) { + count++; + + try { + mSocketUtils.connectSocket(mIp, mPort); + mSocketUtils.write(param.getBytes(UTF_8)); + response = mSocketUtils.read(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + mSocketUtils.disconnect(); + } + + if (response != null || count == 3) { + if (response != null) { + if (!isQueryWeather) { + parseWeatherServerInfo(new String(response, UTF_8)); + count = 0; + isQueryWeather = true; + response=null; + continue; + } else { + parseWeatherJSONString(new String(response, UTF_8)); + } + } + break; + } + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + break; + } + } + } + + + private void parseWeatherServerInfo(String stringJson) { + IcLog.i(TAG, stringJson); + + JSONObject responseJsonObj = JSONObject.parseObject(stringJson); + JSONObject serverInfo = responseJsonObj.getJSONObject("result"); + mIp = serverInfo.getString("weather_ip"); + mPort = serverInfo.getIntValue("weather_port"); + + JSONObject paramJson = new JSONObject(); + paramJson.put("cmd", "getheweatherbycity"); + paramJson.put("city", transformCityName(mCity)); + param = paramJson.toJSONString(); + } + + private void parseWeatherJSONString(String stringJson) { + IcLog.i(TAG, "Response is weather" + stringJson); + + JSONObject responseJsonObj = JSONObject.parseObject(stringJson); + JSONArray jsonArray = responseJsonObj.getJSONArray("HeWeather data service 3.0"); + if (jsonArray.size() > 0) { + JSONObject jsonObjectRoot = jsonArray.getJSONObject(0); + String stringStatus = jsonObjectRoot.getString("status"); + if (stringStatus.equalsIgnoreCase("ok")) { + JSONArray jsonObjectForecast = jsonObjectRoot.getJSONArray("daily_forecast"); + + JSONObject fJson = jsonObjectForecast.getJSONObject(0); + + JSONObject jObjectCond = fJson.getJSONObject("cond"); + JSONObject jObjectTemp = fJson.getJSONObject("tmp"); + + WeatherParcelable weather = new WeatherParcelable(); + WeatherEntity db = new WeatherEntity(); + weather.setCity(mCity); + db.setCity(mCity); + + weather.setStatusDay(jObjectCond.getString("txt_d")); // 白天天气描述 + db.setStatusDay(weather.getStatusDay()); + weather.setStatusNight(jObjectCond.getString("txt_n")); // 夜间天气描述 + db.setStatusNight(weather.getStatusNight()); + + weather.setFigureDay(jObjectCond.getString("code_d")); // 天气索引 + db.setFigureDay(weather.getFigureDay()); + weather.setFigureNight(jObjectCond.getString("code_n")); + db.setFigureNight(weather.getFigureNight()); + + weather.setTemperatureDay(jObjectTemp.getString("min")); // 白天温度-对应“和风天气”的最低温度 + db.setTemperatureDay(weather.getTemperatureDay()); + weather.setTemperatureNight(jObjectTemp.getString("max")); // 夜间温度-对应“和风天气”的最高温度 + db.setTemperatureNight(weather.getTemperatureNight()); + + weather.setUpdateTime(LocalDate.now().format(formatter)); + db.setUpdateTime(LocalDate.now()); + + if (BuildConfig.DEBUG) { + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(weather.getStatusDay()).append("-").append(weather.getStatusNight()) + .append("|") + .append(weather.getTemperatureDay()).append("-").append(weather.getTemperatureNight()) + .append("|") + .append(weather.getUpdateTime()); + IcLog.i(TAG, "Response is weather:" + stringBuffer.toString()); + } + + EventBus.getDefault().post(new WeatherResultEvent(weather)); + //插入数据库 + weatherInjection.deleteDBWeatherDate(); + weatherInjection.insertWeatherEntity(db); + } + } + } + + private static String transformCityName(String cityName) { + String retValue = cityName; + if (cityName != null && !cityName.isEmpty()) { + if (retValue.endsWith("地区")) { + retValue = retValue.substring(0, retValue.length() - 2); + } else if (retValue.endsWith("市") || retValue.endsWith("县") || retValue.endsWith("州") || retValue.endsWith("盟") + || retValue.endsWith("区")) { + retValue = retValue.substring(0, retValue.length() - 1); + } + } + + return retValue; + } +} diff --git a/app/src/main/java/com/ic/work/weather/melon/SocketUtils.java b/app/src/main/java/com/ic/work/weather/melon/SocketUtils.java new file mode 100644 index 0000000..a26ffb8 --- /dev/null +++ b/app/src/main/java/com/ic/work/weather/melon/SocketUtils.java @@ -0,0 +1,49 @@ +package com.ic.work.weather.melon; + +import java.io.IOException; +import java.net.Socket; + +import okio.BufferedSink; +import okio.BufferedSource; +import okio.Okio; + +public class SocketUtils { + private Socket socket; + private BufferedSource source; + private BufferedSink sink; + + public void connectSocket(String host,int port) throws IOException { + socket = new Socket(host,port); + socket.setSoTimeout(15000); + sink = Okio.buffer(Okio.sink(socket.getOutputStream())); + source = Okio.buffer(Okio.source(socket.getInputStream())); + } + + public void write(byte[] param) throws IOException { + sink.writeInt(param.length); + sink.write(param); + sink.flush(); + } + + public byte[] read() throws IOException { + int byteCount = source.readInt(); + if (byteCount>10485760){ + throw new RuntimeException("超出最大可接收字节数"+byteCount); + } + return source.readByteArray(byteCount); + } + + public void disconnect() { + if (socket!=null){ + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + }finally { + socket = null; + sink = null; + source = null; + } + } + } +} diff --git a/app/src/main/jniLibs/arm64-v8a/libICJniUtils.so b/app/src/main/jniLibs/arm64-v8a/libICJniUtils.so new file mode 100644 index 0000000..78b371a Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libICJniUtils.so differ diff --git a/app/src/main/jniLibs/armeabi-v7a/libICJniUtils.so b/app/src/main/jniLibs/armeabi-v7a/libICJniUtils.so new file mode 100644 index 0000000..6f9fd5b Binary files /dev/null and b/app/src/main/jniLibs/armeabi-v7a/libICJniUtils.so differ diff --git a/app/src/main/jniLibs/x86/libICJniUtils.so b/app/src/main/jniLibs/x86/libICJniUtils.so new file mode 100644 index 0000000..9f22c85 Binary files /dev/null and b/app/src/main/jniLibs/x86/libICJniUtils.so differ diff --git a/app/src/main/jniLibs/x86_64/libICJniUtils.so b/app/src/main/jniLibs/x86_64/libICJniUtils.so new file mode 100644 index 0000000..56dbe64 Binary files /dev/null and b/app/src/main/jniLibs/x86_64/libICJniUtils.so differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..20a7f50 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + +